我正在探索Android的VpnService的功能。目前,我通过在用户空间中重建IP堆栈来构建了一个非常基本的请求转发器:我从VpnService的输入流中读取IP数据包,对其进行解析,对于我不希望转发的连接,我尝试重新创建这些数据包。 VPN连接之外的套接字连接。

我知道VpnService.protect()可以帮助实现这一点,并尝试按以下方式实现它:

Socket socket = new Socket();
vpnService.protect(socket);
socket.connect(new InetSocketAddress(
        header.getDestinationAddress(),  // From my IP datagram header
        body.getDestinationPort()));     // From the TCP datagram header

不幸的是,这种方法导致环回VPN接口(interface)。

上面的代码只会阻塞并最终超时,我通过从一个单独的线程调用Socket.connect(InetSocketAddress)来观察回送;连接直接返回到我的VpnService的输入流中,然后重复该过程。

不用说,这会导致循环。我感到这样做的原因是,在创建套接字(以及随后的对VpnService.protect(Socket)的调用)时,我尚未设置目标IP和端口。

似乎确实是这种情况,因为通过在我的VpnService实现中重写VpnService.protect(Socket)VpnService.protect(int)并在两种情况下调用super都返回false。

如何正确保护套接字连接?

最佳答案

以下代码有效。

Socket socket = SocketChannel.open().socket();
if ((null != socket) && (null != vpnService)) {
    vpnService.protect(socket);
}
socket.connect(...);

new Socket()没有有效的文件描述符,因此无法受到保护。

09-28 05:55