Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/223.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android VPN服务-如何转发截获的互联网流量?_Android_Sockets_Networking_Tcp_Vpn - Fatal编程技术网

Android VPN服务-如何转发截获的互联网流量?

Android VPN服务-如何转发截获的互联网流量?,android,sockets,networking,tcp,vpn,Android,Sockets,Networking,Tcp,Vpn,我遵循了这一点,并使用Vpn服务创建了Vpn接口。在将转发路由添加为“0.0.0.0”时,所有internet流量将转发到Vpn接口。我可以读取数据包、访问协议、目标ip和端口 现在我正试图通过tcp套接字将数据包转发到其目的地。但是套接字连接失败,连接超时 exception: java.net.ConnectException: failed to connect to /74.125.227.114 (port 443): connect failed: ETIMEDOUT (Connec

我遵循了这一点,并使用Vpn服务创建了Vpn接口。在将转发路由添加为“0.0.0.0”时,所有internet流量将转发到Vpn接口。我可以读取数据包、访问协议、目标ip和端口

现在我正试图通过tcp套接字将数据包转发到其目的地。但是套接字连接失败,连接超时

exception: java.net.ConnectException: failed to connect to /74.125.227.114 (port 443): connect failed: ETIMEDOUT (Connection timed out)
注意:当我尝试使用相同的ip和端口进行套接字连接,但没有Vpn时,它会被连接。不知道我错在哪里

粘贴以下代码:

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();
    }

我认为您需要使用
VpnService.protect(socket)
保护套接字不被重新路由,如下所述:

您从FileInputStream读取的数据包含IPHeader和TCP/UDP头,然后将它们放入套接字中,这将在其上添加另一个IPHeader和TCP/UDP头。因此,服务器端将获取包含IPHeader和TCP/UDP头的数据,但它认为这些数据是应用程序数据。因此,您无法连接服务器

现在我知道了为什么我不能通过套接字转发数据包。添加ip地址为(0.0.0.0)的vpn路由表条目时,会导致此问题。为了确认,我只添加了特定地址,并且可以看到除了路由表中添加的地址之外的所有其他地址的套接字连接都成功。但是为了拦截所有流量,我找不到比将路由表条目添加为(0.0.0.0)更好的方法。有人知道吗?我不完全确定,如果你想进行双向通信,它是否会起作用。您的TUN接口也在发送第3层数据包,而您的套接字是L4,因此您将数据管道传输到TUN接口的方式可能无法工作,除非您设计自己的TCP+IP数据包。请添加方法getDestinationIP、getDestinationPort和getHeaderLength的定义。我想了解IP数据包是如何工作的。谢谢。@shashank:你终于能解决这个问题了吗?另外,请添加用于提取目标ip和端口的代码。是否可以添加方法的定义?