How do I configure Docker to work with my ens34 network interface (instead of eth0)? - linux

does anyone know how docker decides which NIC will work with the docker0 network? I have a node with two interfaces (eth0 and ens34), however, only the requests that go through eth0 are forwarded to the container.
When my VM was provisioned and Docker was installed, I started a very silly test: I created a centos vm, installed netcat on it and committed the image. Then I started a daemon container listening on port 8080. I used:
docker -it -p 8080:8080 --name nc-server nc-server nc -vv -l 8080
So I tried to connect to the container listening on port 8080 from another node in the same network (in the same IP address as the interface ens34). It did not work.
Whereas when I sent a request from another machine to the IP address from eth0, I saw some reaction in the container (the communication worked). I was "tailing" its output with:
docker logs -ft nc-server
My conclusion with this experiment: there's some mysterious relationship between eth0 (primary NIC) and docker0, and the requests that are sent to ens34 (10.) interface are never forwarded to the veth / docker0 interfaces, only the requests that go through eth0 (9.*). Why's that?
Also, I know I can make everything work if I use --net=host, but I don't want to use that... it doesn't feel right somehow, is it a standard practice to use the HOST mode in Docker containers? Any caveats on that?
--
UPDATE:
I managed to make it work after disabling iptables:
service iptables stop
However, I still don't get what is going on. The info below should be relevant to understand what is going on:
ifconfig
[root#mydockervm2 myuser]# ifconfig | grep -A 1 flags
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
--
ens34: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.21.18 netmask 255.255.255.0 broadcast 10.1.21.255
--
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 9.32.145.99 netmask 255.255.255.0 broadcast 9.32.148.255
--
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
--
veth8dbab2f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::3815:67ff:fe9b:88e9 prefixlen 64 scopeid 0x20<link>
--
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
netstat
[root#mydockervm2 myuser]# netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 9.32.145.1 0.0.0.0 UG 0 0 0 eth0
9.32.145.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.1.21.0 0.0.0.0 255.255.255.0 U 0 0 0 ens34
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 ens34
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
filters
[root#mydockervm2 myuser]# iptables -t filter -vS
-P INPUT ACCEPT -c 169 106311
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 110 13426
-N DOCKER
-N DOCKER-ISOLATION
-A FORWARD -c 0 0 -j DOCKER-ISOLATION
-A FORWARD -o docker0 -c 0 0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -c 0 0 -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -m physdev --physdev-is-bridged -c 0 0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j ACCEPT
-A DOCKER-ISOLATION -c 0 0 -j RETURN
nat
[root#mydockervm2 myuser]# iptables -t nat -vS
-P PREROUTING ACCEPT -c 28 4818
-P INPUT ACCEPT -c 28 4818
-P OUTPUT ACCEPT -c 8 572
-P POSTROUTING ACCEPT -c 8 572
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -c 2 98 -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -c 0 0 -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -c 0 0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8080 -c 0 0 -j MASQUERADE
-A DOCKER -i docker0 -c 0 0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j DNAT --to-destination 172.17.0.2:8080
Thoughts?

First, rule out the obvious and make sure that hosts on the other networks know how to route to your machine to reach the container network. For that, check
netstat -nr
on the source host and make sure that your docker subnet is listed with your docker host as the gateway, or that the default router handling the traffic upstream knows about your host.
If traffic is getting routed but blocked, then you're getting into forwarding and iptables. For forwarding, the following should show a 1:
cat /proc/sys/net/ipv4/ip_forward
Make sure your local host shows a route for the bridges to your container networks with the same netstat command, there should be a line for the docker0 interface and your docker subnet as the destination:
netstat -nr
For iptables, check to see if there are any interface specific nat or filter rules that need to be adjusted:
iptables -t filter -vS
iptables -t nat -vS
If your forward rule defaults to DROP instead of ACCEPT, you may want to add some logging, or just change the default to accept traffic if you believe it can be trusted (e.g. the host is behind another firewall).
This all being said, advertising ports directly on the host is a fairly common practice with containers. For the private stuff, you can setup multiple containers isolated on their internal network that can talk to each other, but no other containers, and you only expose the ports that are truly open to the rest of the world on the host with the -p flag to the run (or ports option in docker-compose).

Related

Starting docker.service fails with "iptables: No chain/target/match by that name"

I've just finished installing docker in a server with Centos, but failed to execute sudo service docker start. Executing sudo service docker restart and reboot the server doesn't help.
The report error by executing sudo dockerd:
Error creating default "bridge" network: Failed to program FILTER chain: iptables failed: iptables --wait -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT: iptables: No chain/target/match by that name.
(exit status 1)
It seems like docker0 cannot be found, so I have checked the iptables by ip a:
...
6: docker0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default
link/ether 02:42:81:95:ec:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
The docker0 exists but its state is DOWN, I don't know if it's the reason.
Some information about my docker (docker --version) and system environment (uname -a):
Docker version 19.03.4, build 9013bf583a
Linux xxxxxxxxxxxxx 4.19.91-009.ali4000.alios7.x86_64 #1 SMP Mon Jan 25 10:47:38 CST 2021 x86_64 x86_64 x86_64 GNU/Linux
Currently I don't know how to fix it.
Update
The result of executing sudo iptables -S is as follows:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -j RETURN

Docker container doesn't have any internet access

After working a long time on why i don't have any internet access into Docker i had to ask here, i read a lot of solutions which posted in this site, my problem don't resolve
what i did before asking here:
1:
pkill docker
iptables -t nat -F
ifconfig docker0 down
brctl delbr docker0
sudo service docker restart
2:
OTHER_BRIDGE=br-b0b70e352d8c
service docker stop
ip link set dev $OTHER_BRIDGE down
ip link set dev docker0 down
ip link delete $OTHER_BRIDGE type bridge
ip link delete docker0 type bridge
service docker start && service docker stop
iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
iptables -t nat -A POSTROUTING ! -o docker0 -s 172.18.0.0/16 -j MASQUERADE
service docker start
3: stopping iptables and docker daemon:
sudo service iptables stop
sudo service docker restart
4:forwarding rules in iptables:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
and then adding DNS into /etc/default/docker:
DOCKER_OPTS="--dns 208.67.222.222 --dns 208.67.220.220"
is another solution to fix this problem? i also tested internet access after rebooting system

Attempting to setup static IP block with ATT Uverse and IP Passthrough to ASUS router

I am trying to accomplish the following setup:
NVG599 <> ASUS RT-AC88U <> Static device
I have an Ubuntu Server running Apache which has been configured to use an internal address 192.x.x.x as well as one of the static IP addresses. I know Apache is running / listening / working. If I browse to the internal address I get the default Apache page. Ubuntu firewall is disabled. I actually have a domain setup that points to this IP address 'http://thelavender.net'
Normally the ATT RG would handle the second subnet / static IP block. What I cannot figure out is how the ASUS would handle these now that its basically taking over all routing duties.
There is a cascading router option in the ATT RG and I have seen some people talking about using this instead. Is this correct?
EDIT
Thinking back, I think 1:1 NAT is what I really need here correct?
EDIT 2
I tried using something along the lines of this:
#!/bin/sh
#
# to restore this configuration, it needs to be saved to /jffs/scripts/nat-start
# on the router.
#
ifconfig eth0:0 WanIP1 netmask 255.255.255.248 up
iptables -t nat -A PREROUTING -i eth0 -d WanIP1 -j DNAT --to-destination 192.168.1.10
iptables -t nat -I POSTROUTING -s 192.168.1.10 -j SNAT --to WanIP1
#
ifconfig eth0:1 WanIP2 netmask 255.255.255.248 up
iptables -t nat -A PREROUTING -i eth0 -d WanIP2 -j DNAT --to-destination 192.168.1.11
iptables -t nat -I POSTROUTING -s 192.168.1.11 -j SNAT --to WanIP2
#
ifconfig eth0:2 WanIP3 netmask 255.255.255.248 up
iptables -t nat -A PREROUTING -i eth0 -d WanIP3 -j DNAT --to-destination 192.168.1.12
iptables -t nat -I POSTROUTING -s 192.168.1.12 -j SNAT --to WanIP3
#
# Port forwards, in case the webui doesn't work, but i think it will. uncomment below if needed.
# iptables -A FORWARD -p tcp --dport 80 -d 192.168.1.10 -j ACCEPT
I only tried the first group and put this in the nat-start script for Merlin to pick up. When I did this and restarted the router, it refused to pick up the WAN IP from the RG.
Any help with this would be appreciated.
EDIT
Voted down but no explanation as to why.
NVG599 LAN address: 192.168.0.254 / 255.255.255.0
RT-AC88U WAN address: 192.168.0.1 / 255.255.255.0
RT-AC88U LAN address: 192.168.1.1 / 255.255.255.0
NVG599 Cascaded Router: Enabled
Cascaded Router Address: 192.168.0.1
Network Address: 107.218.164.224
Subnet Mask: 255.255.255.248
Server: 192.168.1.10 and 107.218.164.225
Startup script for the router:
#!/bin/sh
#
# tell it where to find the server
ip ro add 107.218.164.225/32 via 192.168.1.10
iptables -I POSTROUTING -t nat -s 107.218.164.225/32 -j RETURN
#
# servers 2-N go here
......
#
# catch-all for everything else on the LAN
#
# this will double-NAT everything and will end up using the NVG's dynamic IP which is outside of the static IP block
##iptables -A POSTROUTING -t nat -o eth0 -j SNAT --to 192.168.0.1
#
# this uses one of the public IPs
iptables -A POSTROUTING -t nat -o eth0 -j SNAT --to 107.218.164.230
And script for the server if need be
#!/bin/sh
#
ifconfig eth0:1 107.218.164.225/29
ip ro repl default via 192.168.1.1 src 107.218.164.225

Disable linux internal route?

I have a system with 2 NIC(eth0,eth1),I connect them externally with a cable (use corssover cable or connect them to a same switch).I want to ping eth1 ip address from eth0 and I want to traffic pass externally (through cable) from eth0 to eth1, but linux kernel send the traffic internally and don't allow it to pass over cable, How can I fix this and send traffic externally?
I use ping with "-I eth0" but the problem exists.
The problem is not with the VRF but with loopback which is used whenever kernel detects it can use it instead sending through the wire.
Let's use real MAC addresses and dummy IP addresses and NAT to force kernel to send data through wire:
arp -s IP0 MAC0
arp -s IP1 MAC1
ip route add IP0 dev eth1
ip route add IP1 dev eth0
iptables -t nat -A POSTROUTING -d IP1 -j SNAT --to-source IP0
iptables -t nat -A POSTROUTING -d IP0 -j SNAT --to-source IP1
iptables -t nat -A PREROUTING -d IP0 -j DNAT --to-destination IP0
iptables -t nat -A PREROUTING -d IP1 -j DNAT --to-destination IP1
First, enslave at least one of the interfaces on different VRF then try ping -l eth0 dest
Some helpful resources about VRF on Linux:
https://www.kernel.org/doc/Documentation/networking/vrf.txt
https://renard.chezwam.org/blog/2014/09/vrf-on-linux/index.html
PS: it is much simpler on BSD(rdomain) :)

Making a gateway with virtual machines

I have 2 VMS.
I want the VM#1 to be the gateway of the VM#2.
VM#1 have 2 networks (eth0 - 10.0.2.15 (nat) & eth1 - 192.168.1.1 (internal network)).
VM#2 have 1 network (eth0 - 192.168.1.2 (internal network).
VM#1 can ping http://google.com because of the nat network. But what if I want VM#2 to be able to ping google too?
I'm just begining in that and I'd like to learn how to do it.
Here's what I already done:
VM#1
iptables -A FORWARD -i eth1 -j ACCEPT
iptables -A FORWARD -o eth1 -j ACCEPT
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
VM#2
ip route add default 10.0.2.15 dev eth0
Returns me:
Error: either "to" is duplicate, or "10.0.2.0" is a garbage.

Resources