Originally asked here: https://networkengineering.stackexchange.com/questions/56278/not-able-to-forward-traffic-from-tun-interface-to-lo
I am writing a small VPN server, in which for a certain ip address, I am passing the traffic through an http proxy
.
Current Setup
- TUN interface is up and running at 10.0.2.0/24
iptables configuration
iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
VPN logic
- When I receive an IP packet destined to an address, say
1.2.3.4
, I update it's destination to127.0.0.1
and destination port to12345
. - I recalculate the checksum for both
TCP
andIP
layer
Code
- I parse IP layer and TCP layer using gopackets
- Update the destination port and ip address
- Create a NAT entry in the application layer, so that I can change back the
source_ip
andsource_port
in the response packets
// 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
Expected Output
- Traffic from
tun0
will be forwarded ontoeth0
(even if I don't add that iptable entry, default route will do the same thing) eth0
will be knowing the lo addresses, so will forward the packet to loopback address, and eventually to the proxy running on the localhost
Actual Output
- Packets are lost in-between
tshark -i tun0
shows the packets going out fromtun0
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
- But neither
lo
oreth0
shows the corresponding entry for --dport 12345.