Port forwarding between Docker containers

Currently reading
Port forwarding between Docker containers

5
3
NAS
DS212+
Operating system
  1. Linux
  2. macOS
  3. Windows
Mobile operating system
  1. iOS
Last edited:
So, I'm running the Linuxserver Wireguard and Transmission images on Synology DSM 7.1, and I've got it working almost completely, except the listening port isn't being forwarded from the Wireguard container to the Transmission container. Torrent downloads work, but only passively, so I'd be a leech with this setup.
I've confirmed that the port is successfully being forwarded from the VPN provider down to the wg container, but the postup/predown/postdown commands I'm using in the wg conf apparently aren't doing the job of passing it along to the Transmission container.
Hoping someone has a confluence of expertise in DSM, Docker, and Wireguard. 🙏
Code:
[Interface]
PrivateKey = xxxxxxxxxxxx
Address = xxxxxxxxxx
DNS = xxxxxxxx

PostUp = iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE
Table = 2468
PostUp = wg set wg0 fwmark 1234
PostUp = ip rule add not fwmark 1234 table 2468
PostUp = ip rule add table main suppress_prefixlength 0
PostUp = iptables -I FORWARD -i %i -m state --state NEW -j DROP
PostUp = iptables -t nat -A PREROUTING -p tcp --dport 56981 -j DNAT --to-destination 172.20.0.40:56981
PostUp = iptables -t nat -A PREROUTING -p udp --dport 56981 -j DNAT --to-destination 172.20.0.40:56981

PreDown = iptables -t nat -D PREROUTING -p tcp --dport 56981 -j DNAT --to-destination 172.20.0.40:56981
PreDown = iptables -t nat -D PREROUTING -p udp --dport 56981 -j DNAT --to-destination 172.20.0.40:56981
PreDown = iptables -t nat -D POSTROUTING -o wg+ -j MASQUERADE

PostDown = iptables -D FORWARD -i %i -m state --state NEW -j DROP
PostDown = ip rule del table main suppress_prefixlength 0
PostDown = ip rule del not fwmark 1234 table 2468

[Peer]
PublicKey = xxxxxxxxxx
AllowedIPs = 0.0.0.0/0
Endpoint = xxxxxxx:51820
And here's my Docker compose file. I've tried with SYS_MODULE as a cap_add for the wireguard container, but it doesn't appear to make a difference.
YAML:
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Chicago
    volumes:
      - /volume1/docker/wireguard:/config
    networks:
      default:
        ipv4_address: 172.20.0.50
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped
  transmission:
    image: lscr.io/linuxserver/transmission
    container_name: transmission
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Chicago
      - WEBUI_PORT=9091
      - PEERPORT=56981
    volumes:
      - /volume1/docker/transmission:/custom-cont-init.d:ro
      - /volume1/import:/downloads:rw
    networks:
      default:
        ipv4_address: 172.20.0.40
    ports:
      - 9091:9091
      - 56981:56981
      - 56981:56981/udp
    restart: unless-stopped
networks:
  default:
    name: wgnet
    external: true
I've tried running the Transmission container without exposing port 56981, which may not be necessary (and could potentially create a conflict) as it receives all its traffic from the wg container, but this was no help.
I also run a bash script inside the Transmission container to allow access to the UI and route everything else through the Wireguard container:
Bash:
#!/bin/bash

ip route del default
ip route add default via 172.20.0.50
ip route add 192.168.1.0/24 via 172.20.0.1
This approach is mostly based on a guide offered on Linuxserver.io, with additional info from this site.
I've verified that torrent traffic is going through the VPN. Any ideas for getting that port open? 🙃
 
Adapted some additional iptables commands from this script into my wg0.conf, but the Transmission container still reports that the listening port is closed. 🤔

Code:
PostUp = iptables -A INPUT -p tcp -i wg0 --dport 56981 -j ACCEPT
PostUp = iptables -A INPUT -p udp -i wg0 --dport 56981 -j ACCEPT
PostUp = iptables -A FORWARD -i wg0 -o eth0 -p tcp -d 172.20.0.40 --dport 56981 -j ACCEPT
PostUp = iptables -A FORWARD -i wg0 -o eth0 -p udp -d 172.20.0.40 --dport 56981 -j ACCEPT


PreDown = iptables -D INPUT -p tcp -i wg0 --dport 56981 -j ACCEPT
PreDown = iptables -D INPUT -p udp -i wg0 --dport 56981 -j ACCEPT
PreDown = iptables -D FORWARD -i wg0 -o eth0 -p tcp -d 172.20.0.40 --dport 56981 -j ACCEPT
PreDown = iptables -D FORWARD -i wg0 -o eth0 -p udp -d 172.20.0.40 --dport 56981 -j ACCEPT
 
Fixed it!

The instruction iptables -I FORWARD -i %i -m state --state NEW -j DROP says to drop any incoming packets that would be used to initiate a new connection, which I guess is the very definition of what you’d be listening for on your listening port. 😅

So, the additional iptables instructions in my first reply are unnecessary. I just needed to remove those PostUp and PostDown commands, and my conf works. I hope this can be helpful to someone else! 🙃
 
Congratz!

As an alternative, you could hook containers that depend on the vpn connection into the network namespace of the container that establishes the vpn connection. This way all these containers share the vpn's network interfaces (as in same localhost, same ip for eth0)

Your compose file would need to change like this:
  • only the wireguard container needs to declare network and ports
  • all containers that hook into the wireguard network interface must use network_mode: service:wireguard
    • network and ports proterty can be removed as they don't make sense anymore
Since the containers hook into the network namespace, there is no need to tinker with iptables.
 
Just noticed this post yesterday but was to sleepy to respond with the same reply as @one-eyed-king. Was also missing the point in the 1st read so wanted to sleep on it.

Glad it worked out, but putting one container into a network namespace of VPN one would be my preferred choice as well.
 
I use Gluetun... And in that case the Transmission ports are located under the VPN section, and network_mode: "container: transmission" would be added in the app section, while ditching the network section at the end of your compose.
 
Congratz!

As an alternative, you could hook containers that depend on the vpn connection into the network namespace of the container that establishes the vpn connection. This way all these containers share the vpn's network interfaces (as in same localhost, same ip for eth0)

Your compose file would need to change like this:
  • only the wireguard container needs to declare network and ports
  • all containers that hook into the wireguard network interface must use network_mode: service:wireguard
    • network and ports proterty can be removed as they don't make sense anymore
Since the containers hook into the network namespace, there is no need to tinker with iptables.
Thank you for the suggestion! With that approach, how is the Transmission web UI still accessible without exposing a port and instructing the Transmission container not to route local traffic through the Wireguard container, as with ip route add 192.168.1.0/24 via 172.20.0.1?
 
Like I wrote: the wiregard container needs to publish all ports now, as it's the owner of the network namespace. All other container just hook into it. Whatever ports you published on the other container before, need to move into the ports section of the wiregard container.
 
Oh, I see! That does appear to be a lot easier. Thanks for your reply! (y)
 

Create an account or login to comment

You must be a member in order to leave a comment

Create account

Create an account on our community. It's easy!

Log in

Already have an account? Log in here.

Similar threads

Breaking my previous promise, I'll share the solution that has been working for several weeks now. Reason...
Replies
19
Views
12,393
i've gave up trying to get pihole to work. turned off the container, re-installed adguard home, pointed...
Replies
18
Views
2,757
I have no idea what you are doing, but I just tested it based on the instructions of the guide you linked...
Replies
11
Views
2,794

Welcome to SynoForum.com!

SynoForum.com is an unofficial Synology forum for NAS owners and enthusiasts.

Registration is free, easy and fast!

Trending threads

Back
Top