Docker container inside OpenWrt not accepting traffic from lan

hello,

I created a docker container from alpine and configured it with ssh server.
The container binds to port 2222 when it runs
ssh 127.0.0.1 -p 2222 works
ssh 10.1.1.1 -p 2222 inside openwrt works
ssh 10.1.1.1 -p 2222 from my laptop does not work
the terminal hangs without any error and it outputs a timeout error

dsl400@dsl400-Lab:~$ ssh -v -C -A -X -p 2222 10.1.1.1
OpenSSH_8.2p1 Ubuntu-4ubuntu0.5, OpenSSL 1.1.1f  31 Mar 2020
debug1: Reading configuration data /home/dsl400/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug1: Connecting to 10.1.1.1 [10.1.1.1] port 2222.
debug1: connect to address 10.1.1.1 port 2222: Connection timed out
ssh: connect to host 10.1.1.1 port 2222: Connection timed out
dsl400@dsl400-Lab:~$ 

if the container is not running ssh 10.1.1.1 -p 2222 from my laptop will fail with connection refused

docker run -dit --name test --network my_containers -p 2222:22 test-image
the container runs sshd with -d flag and I can see new log entries when connecting from inside openwrt but nothing shows up when trying to connect from my laptop

thanks

sounds a bit like a host only limitation.

could it be that my_containers is somehow restricted? How is it defined?
Did you already try other networks or the default bridge?

I managed to make it work but only when using the default bridge network

would you share some info first please?

  • openwrt version,
  • docker network you created, what its type, how your created,
  • service dockerd uciadd/ucidel did you use it :
# service dockerd help
Syntax: /etc/init.d/dockerd [command]

Available commands:
        start           Start the service
        stop            Stop the service
        restart         Restart the service
        reload          Reload configuration files (or restart if service does not implement reload)
        enable          Enable service autostart
        disable         Disable service autostart
        enabled         Check if service is started on boot
        uciadd          <interface> <device> <zone> Add docker bridge configuration to network and firewall uci config
        ucidel          <interface> <device> <zone> Delete docker bridge configuration from network and firewall uci config
        running         Check if service is running
        status          Service status
        trace           Start with syscall trace
        info            Dump procd service info
  • if default bridge is working with wan why don't you use that and leave your custom network for non-wan purpose only?

most likely your custom network "hangs in the air", owrt firewall is using zone concept to policing forwarding traffic. if your custom network is not member of any zone (e.g. docker zone) and there is no rule to allow such traffic fw will not allow to forward to wan (or to any other).

  • openwrt version,
Target Platform	x86/64
Firmware Version	OpenWrt 22.03.1 r19777-2853b6d652 / LuCI openwrt-22.03 branch git-22.245.77528-487e58a
  • docker network you created, what its type, how your created,

network is created using docker network create my_containers

root@OpenWrt:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a5b8d93e5633   bridge    bridge    local
166f92d2e42e   host      host      local
16aaabe82cec   none      null      local
09996da2c762   my_containers    bridge    local

  • service dockerd uciadd/ucidel did you use it

nope, did not know about this. Is there a tutorial ?

  • if default bridge is working with wan why don't you use that and leave your custom network for non-wan purpose only?

isolation,
the goal of the project is:

  • git repository on the router
  • containers isolated from my local network
  • containers must access the git repository on the router
  • containers can be accessed via ssh from the internet
  • containers have internet access for software download

your goal to isolate docker that's ok, my question was: if you have a working setup, i.e. docker can access wan as you wanted, why not use this setup for all your containers which requires wan access, and have another docker network which does not access wan (due to necessary fw/network configs are missing anyhow).

am not aware of any tutorial unfortunately. but you can try, cannot you, and let us know? :wink:

in the main bridge (i.e. working configuration) the docker containers can access all my home network

  • service dockerd uciadd/ucidel did you use it

please tell me if I got this right
when using docker create network my_network I should see a new interface

# ip a
...
14: br-1a97bf7c18df: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:27:bd:7e:15 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.1/16 brd 172.19.255.255 scope global br-1a97bf7c18df
       valid_lft forever preferred_lft forever

the next step is to use service dockerd uciadd to add this interface to the uci system

well, dockerd officially supports iptables but not nftables. so you'll need some extra fw rules for isolation.

due to lack of nftables support the "usual" automation which used to work with iptables is missing/not working properly thus you need to add manually those firewall rules. such as (note: rule logic examples only, you can create it via luci or uci whichever you prefer):

  • any traffic from docker zone to this device => reject
  • any traffic from docker zone to lan => reject

also, in theory dockerd uciadd/ucidel would add/delete the interface, device, zone configuration for a "docker network". the uciadd method is used for the default bridge creation too so it should do the same for any docker network.

tried to use uciadd, not sure if this correct, however nothing happend in /etc/config/network

root@OpenWrt:~# service dockerd stop
root@OpenWrt:~# service dockerd uciadd test-br br-7a591e91523a testzone
root@OpenWrt:~# service dockerd start

logread shows

user.notice dockerd-init: Bridge device 'docker0' already defined in network config

edit:
looks like test-br br-7a591e91523a testzone are not passed to uciadd and it defaults to internal values

[ -z "${iface}" ] && {
		iface="docker"
		device="docker0"
		zone="docker"
	}

edit:
managed to solve this using [solved] Service not receiving arguments - #2 by dave14305

docker container now isolated in new network
accepts ssh on port 2222 from lan on the router IP address
no internet access inside the container
cannot access the container from wan via port 2222

docker run --network my_bridge -p 2222:22 ....

after rereading Nftables vs dockerd a few times

ip a | grep :\ br-   to list all existing bridges
docker network create my_network
ip a | grep :\ br-   look for a new bridge device in my case br-09996da2c762
service dockerd stop 
service dockerd uciadd myNetwork br-09996da2c762 myzone
service dockerd start

network / firewall / general settings 
myzone => reject  changed top myzone => wan accept accept accept
config include
        option type 'nftables'
        option path '/etc/forward.nft'
        option position 'chain-append'
        option chain 'forward'

config include
        option type 'nftables'
        option path '/etc/accept_to_docker.nft'
        option position 'chain-prepend'
        option chain 'accept_to_docker'

$ cat /etc/forward.nft
iifname myNetwork jump forward_docker comment "fix: handle docker forward traffic"

$ cat /etc/accept_to_docker.nft
oifname myNetwork  accept comment "fix: accept traffic to docker"

reboot and now containers have internet access
luci / network / firewall / port forwards

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'SSH to MyContainer'
	list proto 'tcp'
	option src 'wan'
	option src_dport '2222'
	option dest_ip '10.1.1.1' << router lan ip addres
	option dest_port '2222'

Saga continues

looks like adding the following lines in /etc/config/firewall makes the internet work inside containers but breaks my internet for the rest of the network

I can access pages that were open prior to the modification but new sites will not load

config include
        option type 'nftables'
        option path '/etc/forward.nft'
        option position 'chain-append'
        option chain 'forward'

config include
        option type 'nftables'
        option path '/etc/accept_to_docker.nft'
        option position 'chain-prepend'
        option chain 'accept_to_docker'

$ cat /etc/forward.nft
iifname myNetwork jump forward_docker comment "fix: handle docker forward traffic"

$ cat /etc/accept_to_docker.nft

after rereading Nftables vs dockerd a few more times

ip a | grep :\ br-   to list all existing bridges
docker network create my_network
ip a | grep :\ br-   look for a new bridge device in my case br-09996da2c762
service dockerd stop 
service dockerd uciadd myNetwork br-09996da2c762 myzone
service dockerd start

in /etc/config/firewall

config zone
  option name myzone
  list device br-09996da2c762 <<  add this line
  option input 'REJECT'
  option forward 'REJECT'
  option output 'ACCEPT'

config forwarding
  option src myzone
  option dest wan

reboot and now internet inside the docker container works

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.