保护VpnService中的套接字

Pau*_*sma 11 sockets vpn android packet-capture android-4.0-ice-cream-sandwich

我正在探索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
Run Code Online (Sandbox Code Playgroud)

不幸的是,这种方法导致VPN接口的环回.

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

不用说,这会导致循环.我觉得这样做的原因是在创建套接字时(以及随后的调用VpnService.protect(Socket)),我还没有设置目标IP和端口.

这似乎确实如此,因为通过覆盖VpnService.protect(Socket)VpnService.protect(int)我的VpnService实现并在两种情况下调用超级都返回false.

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

小智 12

以下代码有效.

Socket socket = SocketChannel.open().socket();
if ((null != socket) && (null != vpnService)) {
    vpnService.protect(socket);
}
socket.connect(...);
Run Code Online (Sandbox Code Playgroud)

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


小智 5

在保护之前你需要绑定你的套接字。这对我有用:

Socket socket = new Socket();
//bind to any address
socket.bind(new InetSocketAddress(0));

vpnService.protect(socket);

socket.connect(...);
Run Code Online (Sandbox Code Playgroud)