Android VpnService - How to forward intercepted internet traffic ?
android, networking, sockets, tcp, vpn
Solution
I think you need to protect the socket from being rerouted with `VpnService.protect(Socket)` as stated here: How to use VPN in Android?
Problem
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(); } ```