10

Script to fix Docker iptables on Synology NAS

 2 years ago
source link: https://gist.github.com/pedrolamas/db809a2b9112166da4a2dbf8e3a72ae9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Author

pedrolamas commented on Aug 18, 2020

edited

Instructions

  • Open DSM on your Synology NAS
  • Open Control Panel and click on Task Scheduler
  • Click Create button, Triggered Task, User defined script
  • Give it a name, select "root" for User and "Boot-up" for Event, tick Enabled
  • Click Task Settings, paste the above script on the User-defined script
  • Click OK button and you're done!

The script will run after every reboot and should survive any updates of DSM!

More info

Please check the following post:

https://www.pedrolamas.com/2020/11/04/exposing-the-client-ips-to-docker-containers-on-synology-nas/

I don't know you but I already love you!
Thanks for the fix, you saved my night !

Thanks a lot! This fixed my issue with Authelia and Traefik not seeing the real originating IP!

I transferred my perfectly working linuxserver/swag container (I love it!) from Debian to Synology NAS and ran into the same issue.

Pedrolamas' solution solved my first fail2ban problem with 172.17.0.1 host in nginx access.log.
Thanks a lot for this!!!

Now fail2ban tries to ban the correct external IP. The word "tries" points to the next problem. But that's stuff for next weekend.

lilws commented on Apr 9, 2021

This is awesome, I'm trying to figure out why my torrent can't catch peers for download, and figure out that NAT is the main problem in docker.

Thanks a lot!

flo-mic commented on Apr 11, 2021

edited

@pedrolamas many thanks for the script. It helped me a lot. I had to make some adaptions to it as some default iptable rules seems to miss in my system (I use default config, noting special here, quite strange...). So if someone else has problems with the script please try the following one. It is nearly the same but just waits for another iptable rule.

This one was tested under Synology DSM 6.2.4-2556 on a 916+

#!/bin/bash
currentAttempt=0
totalAttempts=10
delay=15

while [ $currentAttempt -lt $totalAttempts ]
do
	currentAttempt=$(( $currentAttempt + 1 ))
	
	echo "Attempt $currentAttempt of $totalAttempts..."
	
	result=$(iptables-save)

	if [[ $result =~ "-A DEFAULT_FORWARD -i docker0 -o docker0 -j ACCEPT" ]]; then
		echo "Docker rules found! Modifying..."
		
		iptables -t nat -A PREROUTING ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
		iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
		
		echo "Done!"
		
		break
	fi
	
	echo "Docker rules not found! Sleeping for $delay seconds..."
	
	sleep $delay
done

Author

pedrolamas commented on Apr 12, 2021

Thank you for sharing that @flo-mic! Guess I need to revisit this and try to find a better rule that would cover more cases! slightly_smiling_face

Thank you so much for this.

This fixed my issue. I can now see the client IP addresses in pi-hole running in Docker on my Synology NAS. Thank you!

This does really fix the client resolve problem for ADH in docker.
Really thank you. smile

Was the fix here also, but 3 things;

  1. The second rule never match, so it is useless
  2. The table filter is also blank at the chain FORWARD compared to another - not synology docker installation.
  3. Why are all packages got masquerade without these rule?

@pedrolamas is there any chance to get this also working for ip v6?

Author

pedrolamas commented on Dec 13, 2021

@flo-mic most likely, but I have no idea how to do that...

Fixed also problems with Docker linuxserver/swag

Maypul commented on Jan 30

edited

Hi there, actually I have been running these ip tables rules successfully or so I though but I have noticed something strange happening with these rules on on my Synology DSM 7, once rules are removed, everything works as expected, except getting real ip in my docker apps of course...
So the issue is, I also have to run in synology firewall rules such as All All [docker subnet] to allow my containers to connect to the internet also to talk between each other, I have three subnets. Once this firewall rule is on, with even one iptables rule only some containers are becoming availble bypassing firewall deny deny rule. So if I have allow docker subnet to go through firewall in synology, some containers also get 'allow others to connect to containers from outside' exposing theirs ports on synology even if there is no rule allowing the ports to open. With my setup with containers I had exposed but not allowed though firewall, phpmyadmin and organizzer would be accessible everywhere. For example, qbittorrentvpn or plex would not be unless allowed on firewall.
I have tried host mode on ports in traefik and it did not work for me. As I need to have firewall on and also allow docker containers to the internet, I simply can't use these iptables rules if they open some random containers. Seems like docker on synology and/or iptables are not working really well in there,

Picture reference, if these docker network rules are on, then this leak happens on some containers: http://prntscr.com/26lq4pk Another all rule are just 80 and 443.

Edit 2: I just though of some similarities that applies to both apps that leaked, I am no expert at iptables at all, but both phpmyadmin and organizzer uses 80 port internally in docker, even if I mapped them to other ports to host machine. I am assuming that with these iptables maybe somehow it also opens these apps since they are on themselves open on port 80? I will try to check it later.

But my apps that leaked with these firewall rules in docker had these ports:
phpmyadmin - 8080:80/tcp (checked also 30020:80)
organizr - 82:80/tcp

And those not leaked:
plex - 32400:32400/tcp
arch-qbittorrentvpn - 30000:30000/tcp

And since traefik needs to have open 80 and 443, there would be the similarity... but I will stress it again, I am no expert.

Edit 3: It seems to work as described. Would be great, if that iprule could be somehow adjusted to maybe forward that traffic to specofic container/ip rather that whole docker network as I assume from the rule's '-j DOCKER'.

Maypul commented on Feb 1

edited

I have tried to update the iprules to specific ranges or custom chains but with no success - but I have managed to get correct IP logging on my Traefik instance without modyfing iptables at all and without using host mode (which did not work for me). For anyone interested, in my case I had to add IP of the docker gateway to entrypoints.https.forwardedHeaders.trustedIPs in Traefik (the one IP I was getting in logs). Before I had only Clouldflare IPs in there. Now Traefik and everything behind Traefik gets correct IP in my setup. There is one other thing I had to update in my setup, in my whitelists add: ipStrategy depth: 1 so the whitelist would use the real ip to filter instead of gateway ip.

Edit: Also worked a bit on iptables rules, and finally managed to get them working for me without leaking additional ports. Since I only needed 80 and 433 ports for my proxy, and I though to expand upon dns port that would not get proxied, all I needed instead was:
iptables -t nat -A PREROUTING -p tcp --dport 80 -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A PREROUTING -p tcp --dport 443 -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A PREROUTING -p tcp --dport 53 -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A PREROUTING -p udp --dport 53 -m addrtype --dst-type LOCAL -j DOCKER

which worked exactly as intended and did not provide these leaks mentioned earlier.

@pedrolamas do you have any comments on @ben-ba's comment and @Maypul's comment? I want to be able to get rid of macvlan and transition to using this fix but I'm afraid it will break something in my Syno, like firewall rules.

@Maypul Can you provide the complete script you used to make this persistent during boot up? So if I just want to want SWAG (ports 80 and 443 tcp) and AGH (ports 53 tcp/udp), I just copy the commands you have above?

Maypul commented on Feb 22

edited

@kevindd992002 I have not tried the 'script' to check it after reboot yet as I am still rebuilding my raid on the device, but I basically replaced the rules you can see in original script with mine.

#! /bin/bash

currentAttempt=0
totalAttempts=10
delay=15

HTTP_PORT=81
HTTPS_PORT=444

sed -i "s/^\( *listen .*\)80/\1$HTTP_PORT/" /usr/syno/share/nginx/*.mustache
sed -i "s/^\( *listen .*\)443/\1$HTTPS_PORT/" /usr/syno/share/nginx/*.mustache

while [ $currentAttempt -lt $totalAttempts ]
do
	currentAttempt=$(( $currentAttempt + 1 ))
	
	echo "Attempt $currentAttempt of $totalAttempts..."
	
	result=$(iptables-save)

	if [[ $result =~ "-A DOCKER -i docker0 -j RETURN" ]]; then
		echo "Docker rules found! Modifying..."
		

		iptables -t nat -A PREROUTING -p tcp --dport 80 -m addrtype --dst-type LOCAL -j DOCKER
		iptables -t nat -A PREROUTING -p tcp --dport 443 -m addrtype --dst-type LOCAL -j DOCKER
		iptables -t nat -A PREROUTING -p tcp --dport 53 -m addrtype --dst-type LOCAL -j DOCKER
		iptables -t nat -A PREROUTING -p udp --dport 53 -m addrtype --dst-type LOCAL -j DOCKER

		echo "Done!"
		
		break
	fi
	
	echo "Docker rules not found! Sleeping for $delay seconds..."
	
	sleep $delay
done

Edit: You might want to drop

HTTP_PORT=81
HTTPS_PORT=444

sed -i "s/^\( *listen .*\)80/\1$HTTP_PORT/" /usr/syno/share/nginx/*.mustache
sed -i "s/^\( *listen .*\)443/\1$HTTPS_PORT/" /usr/syno/share/nginx/*.mustache

as it's just for changing synology's default web server ports.

As for commands, you might need to use sudo if trying them in cli first ex sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -m addrtype --dst-type LOCAL -j DOCKER

I see. Will this mess up anything with the Synology firewall?

Maypul commented on Feb 22

@kevindd992002 it still does, maybe not in as big scale as the original command. I also have not been able to find any 'leaks' for now which I sometimes test for. It still forwards traffic, but to specific ports, so it bypasses those. So I can still use synology firewall to manage other rules as ports 80, 443 for me were supposed to be open anyway.

Can I ask every one, this script is work on Dsm 7.1?

Casue I build the linuxServer/chevereto on my synology docker.

But user ip as same my ip, it isn't user real ip.

I just tried this scrpit, I copy all scrpit into User-defined script

like this image, but it isn't work, user upload still my docker ip.

How can I fix it?

image

How do I revert the changes on this script? Just disable the scheduled task and reboot?

Author

pedrolamas commented on Apr 11

How do I revert the changes on this script? Just disable the scheduled task and reboot?

Correct, that should be enough to revert the changes!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK