I have followed this link and created Vpn interface using VpnService. On adding forward route as "0.0.0.0" all internet traffic is forwarded to Vpn Interface. I could read the packets, access protocol, destination ip and port.
Now I am trying to forward the packets to its destination via tcp sockets. But socket connection fails with connection timed out.
exception: java.net.ConnectException: failed to connect to /74.125.227.114 (port 443): connect failed: ETIMEDOUT (Connection timed out)
Note: When I try socket connection with same ip and port, but without Vpn, it gets connected. Not able to figure out where I am going wrong?
Pasting the code below:
public class VpnServiceEx extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "VpnServiceEx";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "TestVpnThread");
mThread.start();
return START_STICKY;
}
@Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
@Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
@Override
public synchronized void run() {
Log.i(TAG,"running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private void runVpnConnection() {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
Socket tcpSocket = new Socket();
boolean ok = true;
// We keep forwarding packets till something goes wrong.
while (ok) {
// Assume that we did not make any progress in this iteration.
try {
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"packet received");
packet.limit(length);
String serverIP = getDestinationIP(packet);
int port = getDestinationPort(packet, getHeaderLength(packet));
Log.d(TAG, "destination IP: " + serverIP + " port: " + port);
InetAddress serverAddr = InetAddress.getByName(serverIP);
SocketAddress socketadd= new InetSocketAddress(serverAddr, port);
tcpSocket.connect(socketadd); *****// this fails******
OutputStream outBuffer = tcpSocket.getOutputStream();
outBuffer.write(packet.array());
outBuffer.flush();
outBuffer.close();
packet.clear();
ok = false;
}
if (tcpSocket.isConnected()) {
InputStream inBuffer = tcpSocket.getInputStream();
byte[] bufferOutput = new byte[32767];
inBuffer.read(bufferOutput);
if (bufferOutput.length > 0) {
String recPacketString = new String(bufferOutput,0,bufferOutput.length,"UTF-8");
Log.d(TAG , "recPacketString : " + recPacketString);
out.write(bufferOutput);
}
inBuffer.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(TAG,"exception: " + e.toString());
ok = false;
}
}
}
private void configure() {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress(getLocalIpAddress(), 24);
builder.addRoute("0.0.0.0", 0); // to intercept packets
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}
I think you need to protect the socket from being rerouted with VpnService.protect(Socket)
as stated here: How to use VPN in Android?
The data you read from the FileInputStream is contains IPHeader and TCP/UDP Header, then you put them in a socket, this will add another IPHeader and TCP/UDP Header on it. So the server side will get the data witch contains IPHeader and TCP/UDP Header, but it think the data is Application data. So you could not connect the server.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With