Linux routing kérdés

Nem megy a routing úgy ahogy szeretném, és nem jövök rá, hogy miért.

Az alap felállás a következő:

* van egy test01 szerver (docker host), amin létrehoztam egy docker internal network-öt, 10.241.32.0/24
* van egy test02 szerver (docker host), amin létrehoztam egy másik docker internal network-öt, 10.241.33.0/24
* mindkét szerveren elindítottam egy-egy konténert "gateway" néven, amin beállítottam wireguard-ot. ezeknek a címei az internal hálózatokon 10.241.32.11 és 10.241.33.11, plusz ezek a bridge hálózatban is benne vannak (elérik az internetet)
* ezen felül a test01 szerveren elindítottam egy busybox01-et is, 10.241.32.12 címmel, illetve a test02 szerver is, ott 10.241.33.12 címmel. Ők csak az internal hálózatokon vannak rajta.
* Elvileg mindenhol beállítottam a route-okat, de a két busybox nem látja egymást, illetve a busybox-ok nem érik a távoli gatweway-eket se.

Móricka rajz:

busybox01 <--> 10.241.32.0/24 <--> gateway01  <--> wireguard <--> gateway02 <--> busybox02

A végső cél az lenne, hogy a test01 és test02 gépeken indítsak különféle konténereket az internal hálózatokon, és ez a konténerek elérjék egymást a gateway-eken keresztül.

A gateway01 és gateway02 ezekkel a beállításokkal van indítva:

    -v /lib/modules:/lib/modules \
    --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
    --sysctl="net.ipv4.ip_forward=1" \
    --cap-add=NET_ADMIN

Amennyire én tudom, ennek elégnek kellene lennie ahhoz, hogy gateway-ként működjön.

Ami már működik: a gateway01 és a gateway02 -őn működik a wireguard kapcsolat, és ők látják egymást.

0ba58a4b5cfc:/config# ip a | grep 10.241
    inet 10.241.32.11/24 brd 10.241.32.255 scope global eth0
0ba58a4b5cfc:/config# ping -c 1 10.241.33.11
PING 10.241.33.11 (10.241.33.11) 56(84) bytes of data.
64 bytes from 10.241.33.11: icmp_seq=1 ttl=64 time=22.2 ms

--- 10.241.33.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 22.161/22.161/22.161/0.000 ms
0ba58a4b5cfc:/config# 
2bc76d2071c6:/config# ip a | grep 10.241
    inet 10.241.33.11/24 brd 10.241.33.255 scope global eth0
2bc76d2071c6:/config# ping -c 1 10.241.32.11
PING 10.241.32.11 (10.241.32.11) 56(84) bytes of data.
64 bytes from 10.241.32.11: icmp_seq=1 ttl=64 time=22.3 ms

--- 10.241.32.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 22.337/22.337/22.337/0.000 ms
2bc76d2071c6:/config# 

A wireguard így néz ki rajtuk (a nyilvános címeket lecseréltem x.y.z.w -re):

0ba58a4b5cfc:/config# wg show
interface: grimdam
  public key: aICWm8W3nJfE7Y/y3ghGHp1GEkBEoCuc0ymodNUh6EA=
  private key: (hidden)
  listening port: 51820

peer: z9XEpgLuNPOfP+0VmubixYd3sqiadpZwfa9ui1Gf8Vk=
  endpoint: x.y.z.w:51820
  allowed ips: 10.241.33.0/24
  latest handshake: 1 minute, 30 seconds ago
  transfer: 4.63 KiB received, 4.38 KiB sent
  persistent keepalive: every 5 seconds
0ba58a4b5cfc:/config# 
2bc76d2071c6:/config# wg show
interface: grimdam
  public key: z9XEpgLuNPOfP+0VmubixYd3sqiadpZwfa9ui1Gf8Vk=
  private key: (hidden)
  listening port: 51820

peer: aICWm8W3nJfE7Y/y3ghGHp1GEkBEoCuc0ymodNUh6EA=
  endpoint: x.y.z.w:51820
  allowed ips: 10.241.32.0/24
  latest handshake: 1 minute, 33 seconds ago
  transfer: 4.26 KiB received, 4.66 KiB sent
  persistent keepalive: every 5 seconds
2bc76d2071c6:/config# 

Hogy kizárjam a tűzfal beállítási hibalehetőségeket, egy forward accept all rule-t adtam hozzá mindkét oldalon. Alább látható a két konténer iptables-save kimenetei. A nat részt nem én adtam hozzá, hanem a docker magától, amit én adtam hozzá az a -A FORWARD -j ACCEPT.

# Generated by iptables-save v1.8.10 (nf_tables) on Sun Feb 25 19:26:57 2024
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -j ACCEPT
COMMIT
# Completed on Sun Feb 25 19:26:57 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Sun Feb 25 19:26:57 2024
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER_OUTPUT - [0:0]
:DOCKER_POSTROUTING - [0:0]
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:43875
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:44004
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 43875 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 44004 -j SNAT --to-source :53
COMMIT
# Completed on Sun Feb 25 19:26:57 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Sun Feb 25 19:27:02 2024
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -j ACCEPT
COMMIT
# Completed on Sun Feb 25 19:27:02 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Sun Feb 25 19:27:02 2024
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER_OUTPUT - [0:0]
:DOCKER_POSTROUTING - [0:0]
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:36441
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:42835
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 36441 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 42835 -j SNAT --to-source :53
COMMIT
# Completed on Sun Feb 25 19:27:02 2024

A route-ok a következők:

0ba58a4b5cfc:/config# ip route
default via 172.17.0.1 dev eth1 
10.241.32.0/24 dev eth0 proto kernel scope link src 10.241.32.11 
10.241.33.0/24 dev grimdam scope link src 10.241.32.11 
172.17.0.0/16 dev eth1 proto kernel scope link src 172.17.0.2 
2bc76d2071c6:/config# ip route
default via 172.17.0.1 dev eth1 
10.241.32.0/24 dev grimdam scope link src 10.241.33.11 
10.241.33.0/24 dev eth0 proto kernel scope link src 10.241.33.11 
172.17.0.0/16 dev eth1 proto kernel scope link src 172.17.0.2 

A wireguard interface neve mindkét oldalon "grimdam", és a két gateway erre route-olja a másol oldal privát hálózatát.

Eddig minden szép és jó. Ezek után elindítok egy busybox-ot a test01 (docker host) gépen úgy, hogy a címe 10.241.32.12, és a gateway01-el azonos internal docker hálózaton van, és hozzáadom a következő static route-ot:

ip route add 10.241.32.0/20 via 10.241.32.11

Ezután próbálom elérni a vele azonos gépen levő gateway-t (10.241.32.11) és a távoli oldalon levőt is (10.241.33.11), és a következőt látom:

/ # ip route
10.241.32.0/24 dev eth0 scope link  src 10.241.32.12 
10.241.32.0/20 via 10.241.32.11 dev eth0 
/ # ping -c 1 10.241.32.11
PING 10.241.32.11 (10.241.32.11): 56 data bytes
64 bytes from 10.241.32.11: seq=0 ttl=64 time=0.182 ms

--- 10.241.32.11 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.182/0.182/0.182 ms
/ # ping -c 1 10.241.33.11
PING 10.241.33.11 (10.241.33.11): 56 data bytes
^C
--- 10.241.33.11 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
/ # 

Tehát a "közeli" gateway01-el van kapcsolat, és a gateway01-nek is van kapcsolata a gateway02-vel. Viszont a busybox01-nek nincs kapcsolata a gateway02-vel.

Ha traceroute-ot próbálok, akkor a gateway01 nem küld vissza ICMP-t:

/ # traceroute 10.241.33.11
traceroute to 10.241.33.11 (10.241.33.11), 30 hops max, 46 byte packets
 1  *  *  *
 2  *  *  *

Mivel a gateway01 nem jelenik meg a traceroute-ban, ezért azt sejtem, hogy a gateway-nél rontottam el valamit, de nem jövök rá, hogy mit.

Mit rontottam el? A route-ok a rosszak, vagy a tűzfal szabályok, vagy valamilyen sysctl-t felejtettem el?

Köszönöm!

Hozzászólások

válaszdzsípítí:

Az általad leírt konfiguráció alapján a hálózati beállítások rendben vannak, és valószínűleg a tűzfal szabályok okozhatják a problémát. Az iptables konfiguráció alapján mindkét gateway-en elvileg megengedted az összes forgalmat a FORWARD chain-ben.

Azonban az látszik, hogy a Docker által generált szabályok futnak a nat table-ben, ami átírja a csomagokat, mielőtt azok elérnék az iptables által definiált saját szabályokat. Ez a DOCKER_POSTROUTING chain-ben történik.

A probléma megoldása érdekében próbáld meg hozzáadni a következő szabályokat az iptables-re, hogy megakadályozd a Docker által generált nat szabályok futtatását a specific IP címekre:

​​​​​​​iptables -t nat -I POSTROUTING ! -o docker0 -s 10.241.32.0/24 -d 10.241.33.0/24 -j MASQUERADE
iptables -t nat -I POSTROUTING ! -o docker0 -s 10.241.33.0/24 -d 10.241.32.0/24 -j MASQUERADE

Ezek a szabályok megakadályozzák, hogy a Docker nat-olja az IP címeket a saját hálózatok között. Próbáld meg ezeket a szabályokat hozzáadni mindkét gateway-en, majd próbáld újra a kapcsolatot a busybox-ok között. Ez segíthet megoldani a problémát.

Szia!

Ebből ilyen lett:

:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER_OUTPUT - [0:0]
:DOCKER_POSTROUTING - [0:0]
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -s 10.241.33.0/24 -d 10.241.32.0/24 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 10.241.32.0/24 -d 10.241.33.0/24 ! -o docker0 -j MASQUERADE
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:40041
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:47235
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 40041 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 47235 -j SNAT --to-source :53

Ez így sajnos nem működik.

Észrevételek:

* Ahogy így írtad, nem a DOCKER_POSTROUTING chain-be szúrja be, hanem a POSTROUTING-ba. Ezt így gondoltad?
* A grimdam nevű wireguard interface-nek nincsen IP címe. A MASQUERADE honnan venné a címet?
* Végül de nem utolsó sorban, én **nem akarok** masquerade-et használni az internal network-ök között. Bár ezt így külön nem írtam le a fórum indító bejegyzésben, de az ellenkezőjét se.

Azt szeretném, hogy a két oldal között a csomagok "simán" lennének route-olva, és minden csomagnál az eredeti forrás és célcím jelenne meg. A MASQUERADE azért nem jó, mert az internal hálózatokon olyan szolgáltatások lesznek, amiknél jogot is kell szabályozni IP cím alapján, plusz a napló file-okban is szeretném ha megjelennének a távoli oldal IP címei. Ezért nem jó lenne, ha egy NAT szabály átírná őket.

Szóval az eredeti "gyári" iptables-ben volt ez a sor:

-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING

Ha a célcím nem a 127.0.0.11/32 -ben van, hanem a 10.241.32.0/20-ban akkor nem is megy át a DOCKER_POSTROUTING -ba, és akkor nincs SNAT.

Ezen felül DNAT sincs, a másik szabály miatt:

-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT

Ezek alapján nincsen se DNAT se SNAT az "alap", módosítás nélküli szabályokkal, így is mennie kellene. Nem értem. :-(

Eddig minden szép és jó. Ezek után elindítok egy busybox-ot a test01 (docker host) gépen úgy, hogy a címe 10.241.32.12, és a gateway01-el azonos internal docker hálózaton van, és hozzáadom a következő static route-ot:

 

ip route add 10.241.32.0/20 via 10.241.32.11

Az a /20 a 32-t és a 33-at is fedi. Eleve nem tudom, honnan jön a 20, mikor végig 24-es hálózatokkal dolgoztál, de az biztos, hogy itt csak a túl oldalnak kéne lenni. Nem vagyok benne biztos, hogy ez s baj, mert a hibás bejegyzés ellenére, lehet, hogy a connected hálózat miatt nem kavarja el a routeot (specifikusabb mask), de gyanúsan nem ezt akartad irni. 

Igen, fedi. Onnan jön a /20, hogy a további célok között szerepel további wireguard peer-ek hozzákapcsolása. A távoli internal network-ök mind ebben a /20-ban vannak; és nem egyesével akarom őket route-olgatni, hanem egyben (prefix based routing). A helyi internal hálózat route-ja pedig valóban specifikusabb, ezért abba nem kavarhat bele (és nem is kavar, az a része jól megy).

Illetve ez fejből nincs meg, de szerintem a forwardot a konténer network namespaceben (magyarán odabent iptablessal) kellene engedni. Vagy legalábbis ott is. Bár tippre accept a default. 

Nem egészen. Az első blokk bekapcsolja a forwardingot, meg megengedi neki, hogy piszkálja a network beállításokat. Külön írtad, hogy " amit én adtam hozzá az a -A FORWARD -j ACCEPT."

Na, ennek szerintem a konténer network namespaceében kellene lenni, nem (vagy nem csak) a hostéban. Más kérdés, hogy a default valószínűleg ACCEPT, tehát valójában jó eséllyel nem kell.

Debugolásnál elfelejteném a wireguardot. Amire neked kell itt, arra felhúznék egy sima UDP tunnelt socat-al, ha azzal megy akkor lehet haladni a wireguard debugolásával.

A másik amit kipróbálnék, hogy Docker helyett veth-ekkel és net namespacekkel reprodukálnám az egészet. Így tuti nincs semmi NAT meg tűzfal szabály ami félreviheti a dolgot.

Amit hiányolok még, az bármiféle packet capture. ICMP-s pingelős debugolás helyett TCP vagy UDP forgalommal (netcat pl.) próbálkoznék és figyelném wiresharkba meddig jut el. Ennél a setupnál nem valószínű, de nekem nagyon sokszor volt hogy vswitch-ek rosszul konfigurált hálókártyák elrontották az UDP checksumot és a cél gép (esetedben gw2) dobta el a csomagot, a routinggal meg minden rendben volt.

Ja nem, wireshark ICMP-vel is menni fog, protokolltól független. Annyi, hogy ha WG vagy más tunnel interfészen tap-elsz, akkor látod majd az ICMP-t, ha meg a docker interfészeken vagy bridge-n tap-elsz, akkor valami tunnelezett csomagok látszanak majd rajta (szerintem UDP-t használ a WG is)

Jól gondolom, hogy wireshark csak akkor fog menni, ha wireguard helyett sima UDP-t próbálok?

Nem. Nyilván attól függően, hogy hol futtatod, fog látszani, hogy "hol veszik el", és a host interfacen már a tunnel packeteket kell lásd, de az kb mindegy, úgyis arra vagy kíváncsi első körben, hogy hol akad meg.

(És a wireshark elég ott, ahol nézegeted, capturera a jó öreg tcpdump elég, szóval nem ügy a konténerben futtatni.)

Annyit fűzék hozzá, hogy tcpdumpban az alap buffer túl nagy kis ICMP csomagoknál 100+ kell hogy azokat kiírja képernyőre interaktív módban (ha eleve file az output, akkor mindegy).

Valamint akkor is ha egyébként megy a DNS lookup a konténerben, érdemes -n kapcsolót használni, name lookup ha nem megy annak nagy a timeoutja és megfoghatja az outputot.

A két "világ" között nem a vpn tunnel a wireguard lenne az átjáró? Nem kellene azt is megadni mint routing?

A gateway01-en meg van adva:

10.241.33.0/24 dev grimdam scope link src 10.241.32.11

A gateway02-őn is:

10.241.32.0/24 dev grimdam scope link src 10.241.33.11

A busybox01-en meg nem, mert ott nincs is olyan interface. Ott a gateway01 címe van megadva gateway-nek:

ip route add 10.241.32.0/20 via 10.241.32.11

Na beállítgattam a tcpdump-okat. A busybox01 -en ha a közeli gateway01-re küldök ping-et, akkor jön válasz.

1	0.000000	10.241.32.12	10.241.32.11	ICMP	104	Echo (ping) request  id=0x0028, seq=1/256, ttl=64 (reply in 2)
2	0.000150	10.241.32.11	10.241.32.12	ICMP	104	Echo (ping) reply    id=0x0028, seq=1/256, ttl=64 (request in 1)

Ezzel párhuzamosan a gateway01-en ezt látom:

3	1.465971	10.241.32.12	10.241.32.11	ICMP	104	Echo (ping) request  id=0x0028, seq=1/256, ttl=64 (reply in 4)
4	1.466032	10.241.32.11	10.241.32.12	ICMP	104	Echo (ping) reply    id=0x0028, seq=1/256, ttl=64 (request in 3)

Minden stimmel.

Ha a busybox01-ről a gateway02-re küldök ping-et, akkor pedig ezt látom a busybox01-en:

1	0.000000	10.241.32.12	10.241.33.11	ICMP	104	Echo (ping) request  id=0x002a, seq=1/256, ttl=64 (no response found!)

és ezt a gateway01-en:

1	0.000000	02:42:ac:11:00:02		ARP	48	Who has 172.17.0.1? Tell 172.17.0.2
2	0.000123	02:42:00:0e:78:f8		ARP	48	172.17.0.1 is at 02:42:00:0e:78:f8

Az ARP-nak valószínűleg semmi köze nincs ehhez, a gateway01-en ICMP csomag egyáltalán nem látszódik.

A tcpdump kapcsolói a kroozo által javasolt "tcpdump -penni any -s 0 -w dumpfile" volt, tehát minden interface-en figyelt.

Namost nem igazán értem, hogy ha a busybox01 -en látszódik, hogy kiment az ICMP request, akkor hogy lehet az, hogy a gateway01-re nem érkezett be? A busybox01-nek összesen két interface-je van, az egyik a loopback, a másik az, amin keresztül direkt módon eléri a gateway01-et:

66ddc7662e40:/config# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
687: eth0@if688: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:f1:20:0c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.241.32.12/24 brd 10.241.32.255 scope global eth0
       valid_lft forever preferred_lft forever

szóval, ha a wireshark szerint kiment az ICMP request, akkor a gateway01 gépen meg be kellett volna, hogy jöjjön. De nem jött.

Az igazából mindegy is, hogy a gateway01 gépen be van-e kapcsolva a forwarding, mert ha nincs, akkor is be kellene érkeznie a csomagnak, de egyéként:

net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.all.mc_forwarding = 0
net.ipv4.conf.default.bc_forwarding = 0
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.mc_forwarding = 0
net.ipv4.conf.eth0.bc_forwarding = 0
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.eth0.mc_forwarding = 0
net.ipv4.conf.eth1.bc_forwarding = 0
net.ipv4.conf.eth1.forwarding = 1
net.ipv4.conf.eth1.mc_forwarding = 0
net.ipv4.conf.grimdam.bc_forwarding = 0
net.ipv4.conf.grimdam.forwarding = 1
net.ipv4.conf.grimdam.mc_forwarding = 0
net.ipv4.conf.lo.bc_forwarding = 0
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.lo.mc_forwarding = 0

További segítséget szeretnék kérni. Úgy látszik hogy hiába a tcpdump meg a debugolás, így se jutok előre. :-(

Megmutatod azt a teljes icmp packetet packetet mac címekkel, hogy hova próbálja küldeni?

Illetve egy "ip a" -t a gateway01ről (és esetleg a hostról, amin futnak) is.

Tényleg elég fura. Mivel a pcap befele az első, kifele meg az utolsó, ezért én arra tippelnék, ezért itt lesz még valami namespace mágia, ami megfogja azt a packetet (ha kiment, akkor a busybox01-en már átment a filtereken, és ha megjött volna a csomag, akkor látszana a gw01-en, akkor is, ha utána dobódik), vagy rossz fele routeolódik.

Csak triviáliák lecsapkodása miatt megnézed, hogy mit mondd az ip r get 10.241.33.11 ?

ICMP request:

0000   08 00 00 00 00 00 02 af 00 01 04 06 02 42 0a f1   .............B..
0010   20 0c 00 00 45 00 00 54 c2 a5 40 00 40 01 21 0b    ...E..T..@.@.!.
0020   0a f1 20 0c 0a f1 21 0b 08 00 c0 f5 00 2c 00 01   .. ...!......,..
0030   08 a9 dc 65 00 00 00 00 84 fb 0e 00 00 00 00 00   ...e............
0040   10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f   ................
0050   20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f    !"#$%&'()*+,-./
0060   30 31 32 33 34 35 36 37                           01234567

Ebben nem látszik a MAC cím, szerintem a "-i any" miatt.

busybox gépen:

66ddc7662e40:/config#  ip r get 10.241.33.11
10.241.33.11 via 10.241.32.11 dev eth0 src 10.241.32.12 uid 0 
    cache 

gateway01 gépen:

684979cc8c7c:/config# ip r get 10.241.33.11
10.241.33.11 dev grimdam src 10.241.32.11 uid 0 
    cache 

Ha -i eth0 -van csinálom akkor:

Frame 1: 98 bytes on wire (784 bits), 98 bytes captured (784 bits)
    Encapsulation type: Ethernet (1)
    Arrival Time: Feb 26, 2024 17:17:14.776890000 CET
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1708964234.776890000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 98 bytes (784 bits)
    Capture Length: 98 bytes (784 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:icmp:data]
    [Coloring Rule Name: ICMP]
    [Coloring Rule String: icmp || icmpv6]
Ethernet II, Src: 02:42:0a:f1:20:0c (02:42:0a:f1:20:0c), Dst: 02:42:0a:f1:20:0b (02:42:0a:f1:20:0b)
Internet Protocol Version 4, Src: 10.241.32.12, Dst: 10.241.33.11
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
    Total Length: 84
    Identification: 0xfbf6 (64502)
    Flags: 0x40, Don't fragment
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 64
    Protocol: ICMP (1)
    Header Checksum: 0xe7b9 [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 10.241.32.12
    Destination Address: 10.241.33.11
Internet Control Message Protocol
    Type: 8 (Echo (ping) request)
    Code: 0
    Checksum: 0x4405 [correct]
    [Checksum Status: Good]
    Identifier (BE): 45 (0x002d)
    Identifier (LE): 11520 (0x2d00)
    Sequence Number (BE): 1 (0x0001)
    Sequence Number (LE): 256 (0x0100)
    [No response seen]
    Timestamp from icmp data: Feb 26, 2024 17:17:14.000000000 CET
    [Timestamp from icmp data (relative): 0.776890000 seconds]
    Data (48 bytes)

és a 20:0b végű mac cím megfelel annak, ami a gatway01 -en van eth01-en:

684979cc8c7c:/config# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: grimdam: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
683: eth0@if684: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:f1:20:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.241.32.11/24 brd 10.241.32.255 scope global eth0
       valid_lft forever preferred_lft forever
685: eth1@if686: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever

viszont a gateway01 -en továbbra se jelenik meg semmi.

Szóval L2 szinten a busybox01-en kimegy az ethernet frame, gateway01-en meg nem jön be.

Ezt mégis hogy???

Ez volt az első két dolog amit írtam a fórum tetején. :-)

* van egy test01 szerver (docker host), amin létrehoztam egy docker internal network-öt, 10.241.32.0/24
* van egy test02 szerver (docker host), amin létrehoztam egy másik docker internal network-öt, 10.241.33.0/24

Ha a pici részletek is érdekelnek, akkor test01 host gépen:

docker network create --attachable --internal --subnet 10.241.32.0/24 grimdam_10_241_32_0__24

test02 host gépen:

 docker network create --attachable --internal --subnet 10.241.33.0/24 grimdam_10_241_33_0__24

A gateway01 és 02 így van létrehozva:

docker create --name "$GW_NAME" \
    --restart=unless-stopped \
    -v "${GATEWAY_DIR}":/config \
    -v /lib/modules:/lib/modules \
    --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
    --sysctl="net.ipv4.ip_forward=1" \
    --cap-add=NET_ADMIN \
    -p "${LISTEN_PORT}:${LISTEN_PORT}/udp" \
    ${LOCAL_OPTS} \
    "$GW_IMG"

docker network connect bridge "$GW_NAME"
docker start "$GW_NAME"

ahol a LOCAL_OPTS -ban ez található a test01 gépen:

--network grimdam_10_241_32_0__24 --ip 10.241.32.11

és ez a test02 gépen:

 --network grimdam_10_241_33_0__24 --ip 10.241.33.11 

illetve nagyon hasonló módon a busybox01 és 02 gépekre:

# busybox01
 --network grimdam_10_241_32_0__24 --ip 10.241.32.12 

# busybox02
 --network grimdam_10_241_33_0__24 --ip 10.241.33.12 

> Nekem az a gyanúm, hogy a host (mint implicit router) csak az egyes konténerek saját IP-jére menő forgalmat forwardolja oda.

Ez szerintem egy tévedés. A docker internal network level2 és nem level3. Nem csinál semmiféle routing-ot. A tcpdump kimenetében is látszódik, hogy a busybox01 egy ethernet frame-et ír ki az eth0 eszközre.

"Ez volt az első két dolog amit írtam a fórum tetején"

Nem teljesen, annyit írtál, hogy internal, tegnap direkt próbáltam keresni a topicban, hogy valahol szerepel-e bármelyik network driver neve említve, akkor még nem volt. Tudom, hogy a bridge lenne a default, de ilyen problémás debuggolásnál nagy "luxus" a default-okat csak úgy feltételezni, és nem leellenőrizni.

"Ez szerintem egy tévedés. ... Nem csinál semmiféle routing-ot"

Ez még bridge esetén sem teljesen biztos. Nem ismétlem el, lentebb írták, hogy hogyan: https://hup.hu/comment/3032195#comment-3032195

Létezik még egy olyan sysctl paraméter is, hogy net.bridge.bridge-nf-call-iptables ami a bridge-en átmenő L2 forgalmat átküldi iptables-en is. Ez szintén bezavarhat, érdemes leellenőrizni.

Régóta vágyok én, az androidok mezonkincsére már!

Szóval L2 szinten a busybox01-en kimegy az ethernet frame, gateway01-en meg nem jön be.

Ezt mégis hogy???

Én is így értelmezem, furcsa. 

Most csak ötletelek, mert rohadtul kéne dolgozni, de rohadtul gyanús, hogy itt valami docker networking csinál mégis valami, mert mi más lenne. Ami kicsit gyanús:

Egyrészt a --internal kapcsoló leírása ezt mondja:

Network internal mode (--internal)

By default, when you connect a container to an overlay network, Docker also connects a bridge network to it to provide external connectivity. If you want to create an externally isolated overlay network, you can specify the --internal option.

Amiből egy kicsit gyanús, hogy lehet, hogy ilyenkor mégsem bridge network készül?

Másrészt a bridge aszongya, hogy van egy ilyen paraméter, ami alapból true

com.docker.network.bridge.enable_ip_masquerade true Enable IP masquerading.

Nem tartom teljesen lehetetlennek, hogy mivel a célcím valahova kintre esik, ezért valami mégiscsak elmasqolja a host felé azt a csomagot ilyenkor. Nem jelenik meg az a ping valamelyik host interfacen?

Amiből egy kicsit gyanús, hogy lehet, hogy ilyenkor mégsem bridge network készül?

# docker network inspect grimdam_10_241_32_0__24 
[
    {
        "Name": "grimdam_10_241_32_0__24",
        "Id": "392493c05ed90496cb24d7aa591699921f8e5a8c5f2e60b8834d9cd1d60daf30",
        "Created": "2024-02-25T13:52:14.080665822Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "10.241.32.0/24"
                }
            ]
        },
        "Internal": true,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

Driver: bridge

> Nem tartom teljesen lehetetlennek, hogy mivel a célcím valahova kintre esik, ezért valami mégiscsak elmasqolja a host felé azt a csomagot ilyenkor. Nem jelenik meg az a ping valamelyik host interfacen?

Jó ezt megnézem. De az azért mégiscsak furcsa lenne, mert  a konténeren belül látszódik hogy becsomagolja egy ethernet frame-be, és úgy küldi ki az eth0-ra. Akkor ez azt jelentené, hogy a docker kiszedi az ethernet frame-ből, átírja az ip header-t, aztán visszacsomagoja egy másik ethernet frame-be. Ilyet azért csak nem csinál? :-D 

Jó ezt megnézem. De az azért mégiscsak furcsa lenne, mert  a konténeren belül látszódik hogy becsomagolja egy ethernet frame-be, és úgy küldi ki az eth0-ra. Akkor ez azt jelentené, hogy a docker kiszedi az ethernet frame-ből, átírja az ip header-t, aztán visszacsomagoja egy másik ethernet frame-be. Ilyet azért csak nem csinál? :-D 

A docker biztosan nem, de hogy valójában ott ilyenkor milyen bridge interface készül, és arra nincs-e valami ostoba szabály, ami elviszi másfele... Mert ugye a docker itt valójában a rendes network stackot maszatolja csak, és lehet, hogy rosszul. Én se látom, abból, amit írtál, de most vagy ez van, vagy a tcpdump hazudik.

meg nem tudom hogy észrevetted-e, hogy csináltam egy példa minimal working example-t ami demonstrálja a hibát, wireguard-tól teljesen függetlenül. Bárki számára elérhető néhány sor beírásával. Ha tényleg segíteni akarsz, akkor fektess bele annyi energiát, hogy begépeled azt a 8 sor kódot, és utána legyél nagyon okos, és írd meg hogy hogyan lehet javítani. Ha csak annyira vagy képes, hogy ismételgeted ugyan azokat a szavakat, akkor az nem segítség. Az valami más.

Megfogadtam. Így legalább nem kell cap NET_ADMIN, és lehet konténeren belül bármilyen userrel futtatni dolgokat, nem csak root-ként.

Konkrétan a host-ra raktam wireguard-ot, és így működik minden. Ja és 5 swarm leader lett, nem kettő. De az adatbázisból továbbra se tudok több mint kettő node-ot, mert nincs rá pénz, és egy ideig nem is lesz.

Mindezektől függetlenül még mindig nem értem, hogy miért nem megy, de lehet hogy elengedem.

Default docker bridge működés az következőképp néz ki nagyvonalakban:

1. Csinál egy bridge-t, pl. docker0 néven
2. Erre rárak egy címet (igen, a bridge-re) pl. 172.17.0.1/16. Ez lesz default gateway minden konténernek + kapnak egy címet az ehhez tartozó subnetből
3. Szintén rákerül NAT szabály docker0-ra, hogy a konténerek egymáson kívül mást IP-ket is láthassanak

Innentől megoldott konténerek egymás közti kommunikációja, mindenki egy ütközési tartományban van. Ha nem az alhálózaton belüli IP a cél cím, abban az esetben is a bridge-hez kerül a csomag, de (ha systcl ip_forward be van kapcsolva) felkerül az IP protocol handlerjének (hiszen van címe) ahol routeolva majd NAT-olva lesz. Innen a POSTROUTING chain, ahol nem a veth lesz a feladó interfész már, hanem a docker0. Magyarán de, pont ez történik, új ethernet frame generálódik, a docker0 IP címével (source IP). Destination cím marad az eredeti, akinek a konténer küldi a csomagot.

A teljesség kedvéért a busybox01-en ez a teljes routing tábla:

10.241.32.0/24 dev eth0 proto kernel scope link src 10.241.32.12 
10.241.32.0/20 via 10.241.32.11 dev eth0 

Ez pedig az iptables:

# Generated by iptables-save v1.8.10 (nf_tables) on Mon Feb 26 15:17:04 2024
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER_OUTPUT - [0:0]
:DOCKER_POSTROUTING - [0:0]
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:39099
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:42220
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 39099 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 42220 -j SNAT --to-source :53
COMMIT
# Completed on Mon Feb 26 15:17:04 2024

Az egyetlen OUTPUT és POSTROUTING szabályban -d 127.0.0.11/32 szerepel, tehát a 10.241.32.0/20 felé menő csomagokra nincs külön rule, az alapértelmezett OUTPUT ACCEPT és INPUT ACCEPT érvényesül.

Szerkesztve: 2024. 02. 26., h – 17:51

wireguard allowedips? verd bele a tavoli oldal routeolando /24-eit is a peer reszbe.

nezd meg a linken a "rajzot", teljesen egyertelmu mit hova kell beletenned. te pont ezt akarod elerni (site2site vpn routeolva, csak kontenerekkel, de ez addig irrelevans, mig a WG-ban nem engeded a forgalmat)...
elso korben ertsd meg a halozati topologiat es a WG site2site-ot hogyan kell felepiteni.
en pl. nem raknam kontenerbe a WG-ot, mert minek, teljesen jo helyen van a hoston is. sot, normalis esetben a hostodon csak belso halo van, a routing/NAT-ot meg elotte lako eszkozon intezed (tisztabb, szarazabb, biztonsagosabb erzes).
a pub ip-ket igyis ugyis bele kell verned, innentol meg az, hogy kontener konfigba vered bele vagy a hoston, tokmindegy. cserebe nem szivat meg a containerd a sajat tuzfal mokolasaval es a WG-t se konfigolja felre kesobbiekben a csodalatos kontenert letrehozo "magic" ha tobb peer-t szeretnel. (lasd tobb peer/allowedips vs. konteneres WG).
es ilyen mokolasok sem kellenek pl, mint localhost egyik portjat NATolgatni egy masik portjara :D

-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:39099
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:42220
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 39099 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 42220 -j SNAT --to-source :53

Ne viccelj már, attól, hogy valaki nem tett oda egy full blown SDNt, meg nem kell neki k8s cluster, és inkább reszel valamit, mert nem akar behúzni egy bazi nagy stacket valamiért, aminek csak egy kis darabja kell, attól még simán lehetnek eszközei. És simán lehet, hogy arra pont van, hogy konfigostol terítsen konténert, arra meg, hogy dinamikusan basztatott konfig függjön ezektől, arra meg nincs.

BTW itt pontosan erről van szó. Minimális HA -t kell csinálnom a projekt végére, és az is elvárás, hogy a HA lábai különböző szolgáltatóknál legyenek. Tehát lesz egy bérelt szerver X szolgáltatónál, egy másik az Y szolgáltatónál, és egy backup szerver meg a cégnél on premise. Ezek között lesznek szétosztva a szoftver komponensek konténerekben. Egyrészt a szolgáltató függetlenség, és a (részben) on premise telepítés miatt nem hiszem, hogy tudnék kész SDN megoldást használni. (De ha valaki tud ilyet, akkor írjátok meg.)

Másrészt itt nem lehet túl sok jogot állítani hálózati szinten, mert erre alig van igény. Arra van igény, hogy a szoftver komponensek VPN mögött legyenek, és hogy aminek nem muszáj, az ne lássa az internetet. Meg arra is van igény, hogy több különböző datacenter-ben is lehessen őket futtatni, amik lehetőleg különböző szolgáltatónál vannak. De arra **szinte** semmi szükség nincsen, hogy az egyik komponens ne lássa a másikat valamilyen business logic alapján.

>  És simán lehet, hogy arra pont van, hogy konfigostol terítsen konténert, arra meg, hogy dinamikusan basztatott konfig függjön ezektől, arra meg nincs.

Ez pontosan így van. Azért kell a szolgáltató függetlenség, meg a több datacenter-ben való működés, hogy magasabb legyen a rendelkezésre állás. Meg ha valami elromlik (vagy mondjuk az egyik szolgáltatóval jogi vita támad), akkor ne álljon le minden.

es ennek mi koze ahhoz, hogy a docker hoston konfigolsz fel egy vpn-t vagy egy kontenerbe erolteted be? mi valtozik meg attol, hogy docker inditja a daemont (azon kivul, hogy a docker szepen meg*ja a halozatot meg ez melle)? mitol lesz nagyobb a rendelkezesedre allasod? hogyan zarja/nem zarja ki, hogy valakivel jogvitaba kerulsz? hogyan viszed at masik bergepre a pub ip-t/kulcsparokat amit beleversz a kontenerbe, stb stb stb... :D
ertem en, hogy kalapacsod van, ezert mindent azzal akarsz megoldani :)

"aminek nem muszáj, az ne lássa az internetet" > akkor ne expose-old a portot pub ip-s docker hoston :) nem mintha nem pont ezt irtam volna picit feljebb.

meg most van lehetoseged elengedni a hakkolast es a docker hostok ele tenni egy minimal VPN/routert (1-5 EUR/ho kb?), a docker hostnak nem adni pub ip-t es rendesen megtervezni/felepiteni a halozatot. :)

es a ket host-os HA-t most felejtsd el, ha jot akarsz magadnak. (min. 3, mindig paratlan, stb...), mert az nem HA lesz, hanem HAHA, amikor majd kezzel babusgatod a split brainedet.

meg most van lehetoseged elengedni a hakkolast es a docker hostok ele tenni egy minimal VPN/routert (1-5 EUR/ho kb?), a docker hostnak nem adni pub ip-t es rendesen megtervezni/felepiteni a halozatot. :)

es a ket host-os HA-t most felejtsd el, ha jot akarsz magadnak. (min. 3, mindig paratlan, stb...), mert az nem HA lesz, hanem HAHA, amikor majd kezzel babusgatod a split brainedet.

Mondjuk ebben azért akad igazság erősen.

Viszont tulajdonképp miért nem futsz egy kört a docker swarmmal? az overlay network megcsinálja neked az encryptelt tunnelt, nem kell semmi varázslat.

Az engem is érdekel, biztos, hogy nem megoldhatatlan, mert csináltunk mi már ilyet anno. :)

De ha tényleg csak az overlay kell, akkor annak simán lehet létjogosultsága. Élesben sose láttam, de egész jó lightweightnek tűnt nem annyira bonyás dolgokra, csak hát a k8s lett a defakto. Mondjuk annak is lehet értelme, hogy megnézz mondjuk egy k3s-t.

ja, és a két nodeos HAt tényleg ne erőltesd, ha nem muszáj. Én kénytelen voltam mostanában olvasni, bármi, ami slightly is modern, az mind valamilyen consensus algoritmusra épít, szóval min 3 láb. Ha tényleg két node kell, akkor lehet menni vissza a balettba ugrálni szopni a cronosync, pacemaker, heartbeat, keepalived földére.

PostgreSQL streaming replication + manual failover a terv. Ez éppen csak annyira HA, hogy ha a primary postgres tönkremegy, akkor néhány percen belül egy parancs kiadásával (manuálisan) helyre lehet hozni. Annyira nagy HA-ra nincsen szükség, mint egy banknál. Néhány 10 perc leállás belefér. Talán még egy óra is. Fél napos viszont nem. Ebben a konkrét felállásban nem létezik olyan hogy "split brain", és az sem számít, ha páros számú node van. Nem mellesleg ezzel van személyes tapasztalatom, pontosan tudom hogy milyen hibák lehetnek, és hogy melyiket hogyan kell kezelni.

Egyébként meg nem erőltetem a két node-os HA-t. Lehet három vagy négy is, mindenesetre indulásnak kettő lesz. Ebben a döntésben nem csak technikai szempontokat kellett figyelembe venni, hanem pénzügyi kockázatot és más dolgokat.

Egyébként én is gondoltam arra (is), hogy bérelt VPN mögé teszem a docker host -okat, és hogy azokon csak belső privát háló van. Csak hát ez ugye nem valósítható meg úgy, hogy összesen két szerver (docker host) van, amiknek ráadásul különböző szolgáltatónál kell lenniük. Ez nem opció. Ez a sok elvárás eléggé bekorlátozza a lehetőségeket.

szivesen, lejjebb kb. mindennel egyetertettetek, amit leirtam :)
HA-rol beszelsz, de nem azt csinalsz. a manual failover nem HA, az annyia "A", amennyire available vagy (vagy akit ezzel megsziva...ize..biztal) attol a minutumtol szamitva, hogy at kell konfigolni a rendszert a replica DB-re...

A db átkonfigolás az egyetlen parancs (repmgr standby switchover), az alkalmazás többi részét meg megyáltalán nem kell átkonfigurálni, de még újraindítani se. Ezt persze te nem tudhatod (honnan is tudhatnád?), de mégis úgy tűnik, mintha mindent is tudnál, és mindenkinél jobban.

Szerkesztve: 2024. 02. 26., h – 22:27

Húú, ez most nagyon kusza :D

Ami eddig tiszta:
Van 2db szerver (test01, test02) és azokon futtatod docker-ben a VM-et (gateway01,gateway02),
azt akarod hogy a 2db szerveren futó dockerek lássák egymást majd a (gateway01, gateway02) keresztűl.

Itt kezdődik pár kérdés ami a fenti leírásból nem derül ki:
"gateway01,gateway02" -ben hogy van/lesz összekötve a többi "lokális" docker VM?

pl.:
br0  - (L2 mode: bridge, ipvlan interface)

Mutatok egy példát, akkor megérted szerintem, hol rontod el.

( test01, test02 )
    $> ip link add name br0 type bridge
    $> ip link set dev br0 up

    $> docker network create \
    --driver ipvlan \
    --opt parent=br0 \
    --opt ipvlan_mode=l2 \
    internal-network
    
( test01 ) ----A oldal
    $> ip address add dev br0 10.241.32.1/24
    
    VM-1
        $> docker run --name gateway01  --ip 10.241.32.11 --network internal-network
        (docker) ip route add default via 10.241.32.1
        (docker) wg0 tunnel (ip: 192.168.0.10)
                 ip route add 10.241.33.0/24 via 192.168.0.20
    VM-2
        $> docker run --name docker1  --ip 10.241.32.101 --network internal-network
        (docker) ip route add default via 10.241.32.11
    
    VM-3
        $> docker run --name docker2  --ip 10.241.32.102 --network internal-network
        (docker) ip route add default via 10.241.32.11
    VM-...

( test02 ) ----B oldal
    $> ip address add dev br0 10.241.33.1/24
    
    VM-1
        $> docker run --name gateway02  --ip 10.241.33.11 --network internal-network
        (docker) ip route add default via 10.241.33.1
        (docker) wg0 tunnel (ip: 192.168.0.20)
                 ip route add 10.241.32.0/24 via 192.168.0.10
    VM-2
        $> docker run --name docker1  --ip 10.241.33.101 --network internal-network
        (docker) ip route add default via 10.241.33.11
    VM-3
        $> docker run --name docker2  --ip 10.241.33.102 --network internal-network
        (docker) ip route add default via 10.241.33.11
    VM-...

> Itt kezdődik pár kérdés ami a fenti leírásból nem derül ki: "gateway01,gateway02" -ben hogy van/lesz összekötve a többi "lokális" docker VM?

Szerintem meg kiderül. A legelső dolog amit leírtam a post tetején az volt, hogy 

* van egy test01 szerver (docker host), amin létrehoztam egy docker internal network-öt, 10.241.32.0/24
* van egy test02 szerver (docker host), amin létrehoztam egy másik docker internal network-öt, 10.241.33.0/24

Tehát úgy vannak összekötve, hogy minden konténer azonos --network -öt használ. 

Én nem ipvlan driver-t használtam, hanem a defaultot, ami a bridge. Azért nem írtam ki a driver típusát, mert ez a default. A bridge driver-nek is jónak kellene lennie. Az ipvlan -ra akkor lenne szükség, ha vlan-okat is szeretnék rajta használni, de azt nem akarok. Milyen más előnye van az ipvlan-nak ebben a konkrét esetben?

De ha úgy gondolod hogy ez segíthet, akkor ki fogom próbálni ipvlan -nal is. De ezen felül meg is szeretném érteni, hogy miért. :-)

VM-2 $> docker run --name docker1 --ip 10.241.32.101 --network internal-network (docker) ip route add default via 10.241.32.11

Nem szeretném, ha ez lenne a default route, de ez mondjuk részletkérdés.

> Mutatok egy példát, akkor megérted szerintem, hol rontod el.

Sajnos a példából nem értettem meg. :-( Kifejtenéd? 

Összekötést ne a docker-féle fogalmakkal akard értelmezni, hanem az OSI-féle modellben gondolkodj.

HOST = server1, server2

Tehát, OSI féle modllben, hogy akarod összekötni a docker féle VM-ket (internal-network)?
1., HOST-on keresztűl OSI L3 mód ( iptables segítségével )
2., HOST-on keresztűl OSI L2 mód ( iptables nélkül )

Másodszor, OSI féle modllben, hogy akarod összekötni a docker féle VM-ket( gateway1, gateway2) a "külső hálózattal (internet)"?
1., HOST-on keresztűl OSI L3 mód ( iptables segítségével )
2., HOST-on keresztűl OSI L2 mód ( iptables nélkül )

A fentiek leírása alapján ez nem derül ki sehonnan, addig nem fog tudni segíteni itt senki.

 

Ezt a részt elírtam, MACVLAN kell ( IPVLAN az más probléma megoldásához való).

    $> docker network create \
    --driver macvlan \
    --opt parent=br0 \
    --opt macvlan_mode=bridge \
    internal-network

Egyiknek sincs köze a VLAN-hoz, MACVLAN a "valódi" bridge, ez egy későbbi fejlesztés a LINUX-nál ( korábban csak a VETH párokkal és a HOST-n lévő iptables szabályok használatával együtt lehetett megoldani docker-VM összekötését a "külső hálózattal").
MACVLAN lehetővé teszi, hogy a HOST-gép iptables használata nélkül kösd össze a "külső hálózattal" ( OSI L2 szint ).

Itt van egy leírás (ezt folyamatosan frissítik):
https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-int…

 

> Tehát, OSI féle modllben, hogy akarod összekötni a docker féle VM-ket (internal-network)?
> 1., HOST-on keresztűl OSI L3 mód ( iptables segítségével )
> 2., HOST-on keresztűl OSI L2 mód ( iptables nélkül )

> Másodszor, OSI féle modllben, hogy akarod összekötni a docker féle VM-ket( gateway1, gateway2) a "külső hálózattal (internet)"?

> A fentiek leírása alapján ez nem derül ki sehonnan, addig nem fog tudni segíteni itt senki.

De ezek egzakt módon kiderülnek, mivel csináltam egy minimal working example-t, amiben nincsen wireguard, nincsen internet se. Összesen csak 3 konténer van benne, és egyetlen internal network. A kérdés le lett redukálva, és a "hogyan akarod" kérdésre az a válasz, hogy "git clone https://github.com/nagylzs/docker_routing_test.git" - és ebben benne van minden a hálózat típusától, a konkrét IP címektől kezdve, a routing táblán és az összes konténer beállításon keresztül minden.

Ehhez képest azt írod, hogy "nem derül ki sehonnan". Összesen 8 sor begépelésével bárki tudja a saját gépén tesztelni és demonstrálni pontosan azt a problémát, amivel szembesültem. Mégis mit tudnék még hozzá tenni?

Szerkesztve: 2024. 02. 27., k – 13:34

Elkezdtem redukálni az egészet egy minimal working example-re. Úgy gondolom ez sokat fog segíteni a hiba megtalálásában, mert a sok gépelés helyett bárki kipróbálhatja magánál a tesztet.  Egyelőre kihagytam belőle a wireguard-ot is, és egy 3 node-ból álló példát raktam össze.

Két internal network van benne:


docker network create --attachable --internal --subnet 10.241.32.0/24 nw_01_02
docker network create --attachable --internal --subnet 10.241.33.0/24 nw_02_03

És ez a három node:

* node01 10.241.32.12 az nw_01_02 hálózaton
* node02 10.241.32.11 és 10.241.33.11 az nw_01_02 és  nw_02_03 hálózatokon
* node01 10.241.33.12 az nw_02_03 hálózaton

Az lenne az első lépés, hogy össze lehessen rakni egy olyant, hogy a node02 végzi a route-ingot a node01 és a node03 között.

Feltöltöttem ide: https://github.com/nagylzs/docker_routing_test

A teszteléshez:

git clone https://github.com/nagylzs/docker_routing_test.git
cd docker_routing_test

# hálózatok létrehozása
./init.sh

# három node indítása 3 különböző terminálban
./start01.sh
./start03.sh
./start02.sh

# takarítás
./cleanup.sh

Így bárki kipróbálhatja, néhány sor begépelésével. 

Viszont elakadtam, mert a node02 nem indul el. Ezt adom meg neki:

--network nw_01_02 --network nw_02_03 --ip 10.241.32.11/24 --ip 10.241.33.11/24

és ezt kapom hibának:

docker: Error response from daemon: invalid config for network nw_01_02: invalid endpoint settings:
invalid IPv4 address: 10.241.33.11/24.

amit nem értek, mivel az nw_02_03 az 10.241.33.0/24, és ebben benne van a 10.241.33.11; nem világos, hogy miért gondolja azt, hogy ez az ip cím az nw_01_02 -höz tartozik. Vagy talán az is lehet, hogy nem így kell megadni a statikus címeit, de akkor hogy? A docker dokumentációban semmit nem találtam arról, hogy hogyan lehetne azt megadni, hogy a --ip kapcsoló melyik hálózatra vonatkozik.

Így, hogy csak a futó docker run közben lehet connect-elni a network-höz, egy nagyon minimálisan bonyolultabb:

git clone https://github.com/nagylzs/docker_routing_test.git
cd docker_routing_test

# hálózatok létrehozása
./init.sh

# három node indítása 3 különböző terminálban
./start01.sh
./start02.sh
./start03.sh

# node2 hozzáadása mindkét network-höz
./connect_02.sh

#
# Itt lehet játszani velük...
#

# takarítás
./cleanup.sh

Amit én tapasztalok az az, hogy nem megy forward, a node01 nem éri el 10.241.33.0/24-ből egyik címet se, a node03 nem éri el 10.241.32.0/24 -ből egyik címet se. A node02 -őn be van kapcsolva a forwarding, és a FORWARD chain-ben default accept van, és nincsen semmiféle forward szabály.

Minden node bridge driver-es network-kel van összekötve, és minden node bind mount-olja a saját könyvtárát a /node alá, és van rajtuk tcpdump.

Én továbbra se látom hogy hol a hiba. Ha valaki szeretne segíteni, akkor a fenti néhány sor begépelésével tudja tesztelni.

Köszönöm!