Первоначально спросил здесь: https://networkengineering.stackexchange.com/questions/56278/not-able-to-forward-traffic-from-tun-interface-to-lo
Я пишу небольшой VPN-сервер, на котором для определенного IP-адреса я пропускаю трафик через http proxy
.
Текущая настройка
- Интерфейс TUN запущен и работает на 10.0.2.0/24
конфигурация iptables
iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
VPN логика
- Когда я получаю IP-пакет, предназначенный для адреса, скажем,
1.2.3.4
, я обновляю его назначение до 127.0.0.1
и порт назначения до 12345
.
- Я пересчитываю контрольную сумму для
TCP
и IP
layer
код
- Я анализирую IP-уровень и TCP-уровень, используя gopackets
- Обновление порта назначения и IP-адреса
- Создайте запись NAT на уровне приложений, чтобы я мог изменить
source_ip
и source_port
в ответных пакетах
// Code to receive packet from tun interface
pkt := gopacket.NewPacket(packet, layers.LayerTypeIPv4, gopacket.DecodeOptions{
NoCopy: true,
Lazy: false,
})
if ntPkt := pkt.NetworkLayer().(*layers.IPv4); ntPkt != nil {
var err error
if tPkt := pkt.TransportLayer().(*layers.TCP); tPkt != nil {
// Adding NAT entry
h.nLock.RLock()
hash := fmt.Sprintf("%s:%d", waterutil.IPv4Source(packet).String(), waterutil.IPv4SourcePort(packet))
if _, ok := h.natTable[hash]; !ok {
h.nLock.RUnlock()
h.nLock.Lock()
h.natTable[hash] = net.TCPAddr{IP: waterutil.IPv4Destination(packet), Port: int(waterutil.IPv4DestinationPort(packet))}
h.nLock.Unlock()
} else {
h.nLock.RUnlock()
}
buf := gopacket.NewSerializeBuffer()
ntPkt.DstIP = h.proxyIP
tPkt.DstPort = layers.TCPPort(h.proxyPort)
tPkt.SetNetworkLayerForChecksum(ntPkt)
err = gopacket.SerializeLayers(buf, h.opts,
ntPkt,
tPkt)
if err != nil {
logger.E("Error while serializing, skipping the changes", err)
return nil
}
copy(packet, buf.Bytes())
}
}
// Code to write packet onto tun interface
Ожидаемый результат
- Трафик с
tun0
будет перенаправляться на eth0
(даже если я не добавлю эту запись iptable, маршрут по умолчанию будет делать то же самое)
eth0
будет знать адреса lo, поэтому перенаправит пакет на адрес обратной связи и, в конечном итоге, на прокси, работающий на локальном хосте
Фактический вывод
- Пакеты теряются в промежутке между
tshark -i tun0
показывает пакеты, выходящие из tun0
2419 279.256438200 10.0.2.3 ? 127.0.0.1 TCP 60 [TCP Retransmission] 47129 ? 12345 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=550203836 TSecr=0 WS=256
- Но ни
lo
, ни eth0
не отображают соответствующую запись для --dport 12345.