Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save updateing/40ea6405c8c9e0aa9434e49ac4df7105 to your computer and use it in GitHub Desktop.
Save updateing/40ea6405c8c9e0aa9434e49ac4df7105 to your computer and use it in GitHub Desktop.

Policy Routing & polipo configuration

  1. NEVER forget the DNS server - it's not reachable via default route on alternative exit! You need to setup a special entry for DNS server to leave from internal network.

  2. DO NOT try to mess with connmark for this purpose. Even if you think you have a sufficient set of rules, things just don't work:

    iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
    iptables -t mangle -A PREROUTING -i veth-host -j CONNMARK --set-mark 1
    iptables -t mangle -A PREROUTING -j CONNMARK --save-mark
    iptables -t nat -A POSTROUTING -s 10.20.30.2 -j MASQUERADE
    ip rule add fwmark 1 lookup 233
    

    Packets from another namespace can be NATed and delivered to correct destination, but the reply will stuck at LAN. Using -j LOG you will find the reply being lost after mangle PREROUTING and before nat PREROUTING. Traffic within LAN, however, is unaffected. You can ping and receive replies from 192.168.1.1, but not 8.8.8.8. Surprise!

  3. ip route get 1.2.3.4 from 2.3.4.5 iif eth0 The from and iif must be included simultaneously, otherwise there will be "Invalid argument".

  4. rp_filter could be troublesome if you want to bridge peer net namespace to real LAN.

  5. Example configuration (using NAT):

    sudo ip netns add special_routing
    sudo ip link add veth-host type veth peer name veth-special
    sudo ip link set veth-special netns special_routing
    
    sudo ip link set veth-host up
    sudo ip addr add 10.20.30.1/24 dev veth-host
    
    sudo ip netns exec special_routing ip link set veth-special up
    sudo ip netns exec special_routing ip addr add 10.20.30.2/24 dev veth-special
    
    sudo iptables -t nat -A POSTROUTING -s 10.20.30.2 -j MASQUERADE
    
    # Host-side routing table
    sudo ip rule add iif veth-host table 233 # Note the "table" here, otherwise 233 will be recognized as "supressor" instead of table ID. And the `iif` is just fine, do not use fwmark.
    sudo ip route add table 233 default via 192.168.1.161 # You want this, but you have to do a lot more
    sudo ip route add table 233 10.20.30.0/24 dev veth-host # Subnet routes are not auto set
    sudo ip route add table 233 172.31.1.1 via 172.28.84.1 dev enp1s0 # <------!!!!!!!! This can not be reached using default route
    sudo ip route add table 233 192.168.1.10/24 dev enp3s1 # Subnet routes are not auto set
    
    # Peer routing table
    sudo ip netns exec special_routing ip route add default via 10.20.30.1 # Quite normal
    sudo ip netns exec special_routing ip route add 10.20.30.0/24 dev veth-special # Subnet routes
    
    # Kick off proxy
    sudo ip netns exec special_routing polipo &
  6. A practical script

    #!/bin/sh
    
    NETNS=special_routing
    EXEC_IN_NETNS="ip netns exec $NETNS"
    
    ip netns add $NETNS
    ip link add veth-host type veth peer name veth-special
    ip link set veth-special netns $NETNS
    ip link set veth-host up
    $EXEC_IN_NETNS ip link set veth-special up
    
    ip addr add 10.98.99.1/24 dev veth-host
    $EXEC_IN_NETNS ip addr add 10.98.99.2/24 dev veth-special
    
    $EXEC_IN_NETNS ip route add default via 10.98.99.1 dev veth-special
    
    iptables -t nat -A POSTROUTING -s 10.98.99.2 -j MASQUERADE
    
    ip rule add iif veth-host lookup 100
    ip route add table 100 default via 192.168.1.250 dev enp3s1
    ip route add table 100 192.168.1.0/24 dev enp3s1
    ip route add table 100 10.98.99.0/24 dev veth-host
    
    # 8.8.8.8 goes through 192.168.1.250 as well, no need for separate entry
    $EXEC_IN_NETNS polipo proxyPort=9123 dnsNameServer=8.8.8.8 &
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment