0

I'm trying to setup a proxy server in docker container in order to route some packets out of VPN (some sites does not respond to the VPN's ip, they are country locked). In order to do that, I try to mark packets which are send to and from docker container interface.

I use proxy server container connected to user-defined bridge docker network (172.18.0.0/16) with virtual interface named br-43cb854b8af8. Name of the physical network interface on my PC is enp3s0. There is also standard docker bridge interface docker0 with net 172.17.0.0/16, so while it is included in the iptables rules it is not used.

On the start of the PC tables raw and mangle are empty,

filter table:

-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o br-43cb854b8af8 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-43cb854b8af8 -j DOCKER
-A FORWARD -i br-43cb854b8af8 ! -o br-43cb854b8af8 -j ACCEPT
-A FORWARD -i br-43cb854b8af8 -o br-43cb854b8af8 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i br-43cb854b8af8 -o br-43cb854b8af8 -p tcp -m tcp --dport 3128 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-43cb854b8af8 ! -o br-43cb854b8af8 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-43cb854b8af8 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN

nat table:

-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-43cb854b8af8 -j MASQUERADE
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 3128 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-43cb854b8af8 -j RETURN
-A DOCKER ! -i br-43cb854b8af8 -p tcp -m tcp --dport 3128 -j DNAT --to-destination 172.18.0.2:3128

The problem is that if I add

iptables -t mangle -A PREROUTING -i br-43cb854b8af8 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -i enp3s0 -s 172.18.0.0/16 -j MARK --set-mark 1

to mark outgoing packets from proxy server, the second rule does not applies to any packets, while first one does and while masquerading through enp3s0 also works. In other words, packets go as they should, but rule iptables -t mangle -A PREROUTING -i enp3s0 -s 172.18.0.0/16 -j MARK --set-mark 1 for some reason is not applied. Also there is not turned on VPN or any applied ip routes or rules aside from the default ones.

2
  • 1
    The 2nd rule would match incoming packets but the source address prevents (even) this. Container's packets never come from enp3s0. As you never wrote why you'd want this 2nd rule to apply (see What is the XY problem?) I can't continue further. Then to cut the questions, in addition to explaining why and not only how, if you have prepared something with this mark (such as a routing table and routing rules) you should also add it in the question. Commented Oct 8, 2022 at 13:59
  • @A.B Thanks, a lot, the only question which I asked was about second rule, because I wrongly interpreted meaning of -i option, with your answer I was able to resolve a problem in understanding of some stuff with iptables, so at the end for what I was needed the first option would suffice. Again, appreciated. I would probably add my final script as answer to the question, to make some use of it for the community of StackExchange. Commented Oct 8, 2022 at 14:46

1 Answer 1

1

First of all as it has been answered in a comment to the question, 2nd rule is not applicable because -i means that the packet was received from interface enp3s0. So in order to mark all the outgoing packets from proxy first rule would suffice. In order to do the same for the incoming packets we need to add

iptables -t mangle -A FORWARD -i enp3s0 -d 172.18.0.0/16 -j MARK --set-mark 1

So, now then all packets for and from br-43cb854b8af8 are marked (but the one which are sent from browser to proxy), it is time set routes.

First group of commands is

ip rule add to 172.18.0.0/16 pref 100 table 1
ip rule add fwmark 0x0001 pref 101 table 1
ip route add table 1 to 172.18.0.0/16 dev br-43cb854b8af8

They allow to traffic from browser and incoming traffic for proxy go straight to the docker network. Options pref are used, because VPN also sets its rules, which we want to be checked only if the rules above are not applicable to packets.

The second group of commands is

ip rule add fwmark 0x0001 pref 102 table main

It sets it so that if packet has a mark and not going to docker's net (which means that it is outgoing from docker's net) it would avoid rules of VPN and move by his standard route without VPN.

Final script

#!/bin/sh

iptables -t mangle -A PREROUTING -i br-43cb854b8af8 -j MARK --set-mark 1
iptables -t mangle -A FORWARD -i enp3s0 -d 172.18.0.0/16 -j MARK --set-mark 1

ip rule add to 172.18.0.0/16 pref 100 table 1
ip rule add fwmark 0x0001 pref 101 table 1
ip route add table 1 to 172.18.0.0/16 dev br-43cb854b8af8

ip rule add fwmark 0x0001 pref 102 table main

ip route flush cache

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.