Iptables – How to route traffic through different interfaces based on the port number

iproute2iptableslinux-networkingnetworkingsocks

iptables -A PREROUTING -i usb0 -t mangle -p tcp --dport 8080 -j MARK --set-mark 1

iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

// route the traffic with mark 1 to myusb0 table

ip rule add fwmark 1 table myusb0

ip route ls

192.168.0.0/24 dev usb1  proto kernel  scope link  src 192.168.0.136  metric 1 
192.168.3.0/24 dev usb0  proto kernel  scope link  src 192.168.3.182  metric 1 

ip rule ls

0:  from all lookup local 
32762:  from all fwmark 0x1 lookup myusb0 
32763:  from 192.168.3.0/24 lookup myusb0 
32764:  from 192.168.0.1/24 lookup myusb1 
32766:  from all lookup main 
32767:  from all lookup default 

ip route ls table myusb0

default via 192.168.3.2 dev usb0 

ip route ls table myusb1

default via 192.168.0.1 dev usb1

// open up socks on port 8080

ssh -f -N -D 0.0.0.0:8080 root@192.168.3.182

// check if it works

curl –socks5 192.168.3.182:8080 ip.appspot.com

channel 1: open failed: administratively prohibited: open failed
curl: (7) Failed to receive SOCKS5 connect request ack.

I have two Internet connections from two different ISPs and I would like to open up a proxy/socks5 on each one. I thought it would make sense to associate each interface with a port number so that we can manage the connections.

I've created two routing tables (myusb0 and myusb1) for each device (usb1 and usb0), then marked the traffic based on the port number (e.g. on port 8080 I mark it 1) and route the traffic on that mark to the specific table (myusb0). Then I tried to open a socks5 on that IP and tried it locally but for some reasons it doesn't work.

Once I get it working locally I think I should open up the socks in a reverse manner so that I can make it available to the remote server(s) that need to use it.

Any idea why it's not currently working and how I should fix it? For some reasons I think the socks connection is trying the default gateway from the main table which is not set instead to follow the port 8080 mark rule and try the myusb0 table. I'm using Ubuntu (latest version).

Should be mentioned that both ISPs provide dynamic IPs

Edit

As I suspected it seems that the traffic to port 8080 is not being routed (nevermind the socks issue) but I don't know why

 curl portquiz.net:8080 
curl: (7) Couldn't connect to server

Best Answer

Actually, when you do:

$ ssh -f -N -D 0.0.0.0:8080 root@192.168.3.182
$ curl --socks5 192.168.3.182:8080 ip.appspot.com

The following events occur:

  1. CURL opens a TCP connection from [YOUR-HOST]:[RANDOM-PORT] to the SOCKS server that SSHD runs on 192.168.3.182:8080
  2. SSHD accepts the connection
  3. CURL asks SSHD to open a new connection from 192.168.3.182:[RANDOM-PORT] to ip.appspot.com:80
  4. SSHD tries to open a TCP connection and fails
  5. SSHD returns a failure message: "channel 1: open failed: administratively prohibited: open failed"

SSHD can't open a new connection because IP packets destinated to ip.appspot.com:80 are being generated in the router box - not being routed through it. Because of that, packets don't receive the mark, kernel skips both myusb0 and myusb1 tables and the absence of a matching route entry in main table causes a network unreachable error. If you wanted to manage locally-generated packets, the right chain under mangle table would be OUTPUT instead of PREROUTING.

About the port test problem:

$ curl portquiz.net:8080 
curl: (7) Couldn't connect to server

Please, check router configuration:

  1. Is there a default gateway in the "main" table?

    $ ip route show
    
  2. Is packet forwarding enabled?

    $ cat /proc/sys/net/ipv4/ip_forward
    
  3. Are packets being NATed?

    $ iptables -t nat -nvL
    # iptables -t nat -A POSTROUTING -o myusb0 -j MASQUERADE
    # iptables -t nat -A POSTROUTING -o myusb1 -j MASQUERADE