-1

最初在这里问: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层的校验和

代码

  • 我使用gopackets解析 IP 层和 TCP 层
  • 更新目的端口和IP地址
  • 在应用层创建一个 NAT 条目,以便我可以将响应数据包中的source_ipand改回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 地址,因此会将数据包转发到环回地址,并最终转发到在 localhost 上运行的代理

实际输出

  • 数据包在中间丢失
  • 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 的相应条目。
4

1 回答 1

0

发现问题:

  • 网络配置没问题。
  • 通过 go 代码对数据包进行序列化是错误的

  • 错误代码

err = gopacket.SerializeLayers(buf, h.opts,
                    ntPkt,
                    tPkt)                
err = gopacket.SerializePacket(buf, h.opts, pkt)                
于 2019-01-23T07:54:08.780 回答