Невозможно перенаправить трафик с интерфейса `tun` на` lo` - PullRequest
0 голосов
/ 21 января 2019

Первоначально спросил здесь: 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.

1 Ответ

0 голосов
/ 23 января 2019

Найдена проблема:

  • Конфигурация сети была в порядке.
  • Неправильная сериализация пакетов через код go

  • Неправильный код

err = gopacket.SerializeLayers(buf, h.opts,
                    ntPkt,
                    tPkt)                
err = gopacket.SerializePacket(buf, h.opts, pkt)                
...