Zend certified PHP/Magento developer

Can you forward packets from TUN to router on a Mac?

I’m intercepting packets on a toy packet sniffer I have that just pulls all traffic off a TUN device. I’ve setup a default route to the TUN on my mac via:

sudo route -n add default 10.1.0.10

where 10.1.0.10 is the IP of the utun5 device. While I can see the packets coming through to my program, I want to just print them then forward them off to the router. For example, if I were to curl google.com or ping yahoo.com I would see the packet, but the client would still get the expected response as normal.

I feel like on Linux, this isn’t too hard with IP forwarding, NAT and of course, iptables via iproute2. On Mac, I just can’t crack how this is supposed to work. Any help or reading is appreciated.

From the coding side, I’m using Go and the water library for simplifying the creation of the tun device.

Here is a basic implementation:

package main

import (
    "log"
    "net"

    "github.com/songgao/water"
    "golang.org/x/net/ipv4"
)

func main() {
    ifce, err := water.New(water.Config{
        DeviceType: water.TUN,
    })
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Interface Name: %sn", ifce.Name())

    packet := make([]byte, 2000)

    // Replace "en0" with your internet-facing network interface name
    internetInterface, err := net.InterfaceByName("en0")
    if err != nil {
        log.Fatal(err)
    }

    conn, err := net.ListenPacket("ip4:4", "0.0.0.0") // Listen for IPv4 packets
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    rawConn, err := ipv4.NewRawConn(conn)
    if err != nil {
        log.Fatal(err)
    }

    for {
        n, err := ifce.Read(packet)
        if err != nil {
            log.Fatal(err)
        }

        header, err := ipv4.ParseHeader(packet[:n])
        if err != nil {
            log.Printf("Error parsing IPv4 header: %v", err)
            continue
        }

        cm := &ipv4.ControlMessage{
            IfIndex: internetInterface.Index,
        }

        err = rawConn.WriteTo(header, packet[header.Len:n], cm)
        if err != nil {
            log.Printf("Error writing packet to raw socket: %v", err)
        }
    }
}