Запись в выходной поток VpnService не дает ответа
Мое приложение реализует VpnService для перехвата сетевого трафика и предоставления индивидуальных ответов. Цель состоит в том, чтобы обрабатывать трафик на определенные адреса и отбрасывать другие запросы.
В настоящее время я успешно разбираю входящие запросы, строю и отправляю ответы. Проблема, однако, заключается в том, что эти ответы не поступают как фактический ответ на исходный запрос; тестирование с сокетным соединением просто истекло.
Чтобы сделать это различие, в настоящее время я анализирую необработанные IP-пакеты из входного потока VpnService следующим образом:
VpnService.Builder b = new VpnService.Builder();
b.addAddress("10.2.3.4", 28);
b.addRoute("0.0.0.0", 0);
b.setMtu(1500);
...
ParcelFileDescriptor vpnInterface = b.establish();
final FileInputStream in = new FileInputStream(
vpnInterface.getFileDescriptor());
final FileOutputStream out = new FileOutputStream(
vpnInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
try {
while (vpnInterface != null && vpnInterface.getFileDescriptor() != null
&& vpnInterface.getFileDescriptor().valid()) {
packet.clear();
SystemClock.sleep(10);
// Read the outgoing packet from the input stream.
final byte[] data = packet.array();
int length = in.read(data);
if (length > 0) {
packet.limit(length);
/*
1. Parse the TCP/UDP header
2. Create an own socket with the same src/dest port/ip
3. Use protect() on this socket so it not routed over tun0
4. Send the packet body (excluding the header)
5. Obtain the response
6. Add the TCP header to the response and forward it
*/
final IpDatagram ip = IpDatagram.create(packet);
...
}
}
IpDatagram - это класс, через которыйcreate()
анализирует байтовый массив в представление IP-пакета, содержащего IP-заголовок, параметры и тело. Я продолжаю разбирать байтовый массив тела в соответствии с типом протокола. В этом случае меня интересует только IPv4 с полезной нагрузкой TCP - здесь я также создаю представление заголовка TCP, параметров и тела.
После получения экземпляра IpDatagram я могу определить IP-адрес источника и назначения (из заголовка IP) и порт (из заголовка TCP). Я также подтверждаю флаги запроса TCP (такие как SYN, ACK и PSH) и порядковый номер. В приложении:
Впоследствии я создаю новую IpDatagram в качестве ответа, где:
IP-адрес источника и получателя отменяется из входящего запроса;Порты источника и назначения возвращаются из входящего запроса;Номер подтверждения TCP устанавливается на порядковый номер входящего запроса;Фиктивная полезная нагрузка HTTP / 1.1 предоставляется в качестве тела TCP.Я преобразовываю полученную IpDatagram в байтовый массив и записываю его в выходной поток VpnServer:
TcpDatagram tcp = new TcpDatagram(tcpHeader, tcpOptions, tcpBody);
IpDatagram ip = new Ip4Datagram(ipHeader, ipOptions, tcp);
out.write(ip.toBytes());
Мое приложение отображает исходящую дейтаграмму, как и должно быть, но, тем не менее, все соединения все еще имеют тайм-аут.
Вот пример входящего пакета TCP / IP в шестнадцатеричном формате:
4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b00000000a00239089a570000020405b40402080a00bfb8cb0000000001030306
И полученный исходящий пакет TCP / IP в шестнадцатеричном виде:
450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421
Тем не менее, простой тест просто истекает; Я создаю новый сокет и подключаю его к указанному выше IP-адресу, но ответ, представленный выше, никогда не приходит.
Что может быть не так? Есть ли способ выяснить, почему мой ответ не приходит?