Puncte:5

Folosind redirecționarea iptables, păstrând în același timp IP-ul sursă

drapel ng

Am un server care rulează Wireguard (deci are nevoie mascaradă) și un container care rulează pe portul 2525.

Am urmatoarele iptables reguli:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.1:2525
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Când vă conectați la server:2525 direct, containerul Docker poate vedea adresa mea IP reală (1.2.3.4). La conectarea la port server:25, containerul Docker vede IP-ul local furnizat de rețeaua docker:

Apr 07 12:45:46 mx postfix/smtpd[87]: conexiune pierdută după CONECTARE de la necunoscut[172.18.0.1]
Apr 07 12:45:46 mx postfix/smtpd[87]: deconectare de la comenzi necunoscute[172.18.0.1]=0/0

Cum mă asigur că containerul Docker vede corect adresa IP publică în timp ce mă conectez la portul 25 (și nu numai când mă conectez la portul 2525).

Mulțumiri

# iptables -L -n -v -t nat
PRERUTARE în lanț (politica ACCEPT 0 pachete, 0 octeți)
 pkts bytes target prot opt ​​in out source destination
52300 3131K DNAT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 la:172.18.0.1:2525
 150K 8524K DOCKER toate -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE se potrivește cu dst-type LOCAL

INTRARE în lanț (politica ACCEPT 0 pachete, 0 octeți)
 pkts bytes target prot opt ​​in out source destination

Ieșire în lanț (politica ACCEPT 0 pachete, 0 octeți)
 pkts bytes target prot opt ​​in out source destination
    2 120 DOCKER toate -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE se potrivește cu dst-type LOCAL

POSTROUTING în lanț (politica ACCEPT 0 pachete, 0 octeți)
 pkts bytes target prot opt ​​in out source destination
 3385 256K MASQUERADE toate -- * !docker0 172.17.0.0/16 0.0.0.0/0
1733K 104M MASQUERADE toate -- * !br-b147ffdbc9f3 172.18.0.0/16 0.0.0.0/0
    0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:53
    0 0 MASQUERADE udp -- * * 172.17.0.2 172.17.0.2 udp dpt:53
    0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:25

Lanț DOCKER (2 referințe)
 pkts bytes target prot opt ​​in out source destination
   12 1419 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
    0 0 RETURN all -- br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0
   56 3192 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5354 la:172.17.0.2:53
    0 0 DNAT udp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:5354 la:172.17.0.2:53
  107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 to:172.18.0.2:25
# adresă ip
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue stare UNKNOWN grup implicit 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 pentru totdeauna preferred_lft pentru totdeauna
    inet6 ::1/128 scope host
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 32:d0:56:15:0a:64 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname ens3
    inet 159.223.80.86/20 brd 159.223.95.255 scope global eth0
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet 10.15.0.19/16 brd 10.15.255.255 scope global eth0:1
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet6 2400:6180:0:d0::f57:6001/64 domeniu global
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet6 fe80::30d0:56ff:fe15:a64/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 32:dc:4a:e4:27:be brd ff:ff:ff:ff:ff:ff
    altname enp0s4
    altname ens4
    inet 10.130.244.15/16 brd 10.130.255.255 scope global eth1
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet6 fe80::30dc:4aff:fee4:27be/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue stare UNKNOWN grup implicit qlen 1000
    link/niciuna
    inet 10.200.200.52/24 scope global wg0
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
5: wg1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue stare UNKNOWN grup implicit qlen 1000
    link/niciuna
    inet 10.222.111.1/24 scope global wg1
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
6: br-b147ffdbc9f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP grup implicit
    link/ether 02:42:46:21:70:c0 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-b147ffdbc9f3
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet6 fe80::42:46ff:fe21:70c0/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP grup implicit
    link/ether 02:42:66:22:41:91 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
    inet6 fe80::42:66ff:fe22:4191/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
9: veth31eff9d@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 stare UP grup implicit
    link/ether e6:fb:80:5d:c7:a3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e4fb:80ff:fe5d:c7a3/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
19: veth01269f5@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-b147ffdbc9f3 stare UP grup implicit
    link/ether 36:f4:e7:43:5f:da brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::34f4:e7ff:fe43:5fda/64 scope link
       valid_lft pentru totdeauna preferred_lft pentru totdeauna
setenforce 1 avatar
drapel us
se pare că aveți o regulă de postrouting SNAT când mergeți la interfața docker, pe care o puteți șterge. Puteți adăuga, vă rog, rezultatul `iptables -L -n -v -t nat`?
eKKiM avatar
drapel lr
Puteți elabora mai multe despre infrastructura/configurarea rețelei, inclusiv partea wireguard? Pentru mine (în acest moment) nu este clar de ce este necesară mascarada.
drapel ng
@setenforce1 adăugat la postarea inițială
drapel ng
@eKKiM Cred că este necesar pentru rutarea corectă (adică acționează ca gateway/VPN: client -> server WG -> internet)
eKKiM avatar
drapel lr
Este serverul WG și gateway-ul dvs. implicit în rețeaua dvs.? Puteți adăuga rezultatul `ifconfig -a` sau `ip addr`?
drapel ng
Nu, este un server digital oceanic. eth0 are un IP public. S-a adăugat „adresa ip” la postarea de origine.
eKKiM avatar
drapel lr
Nu văd un motiv pentru toate acele reguli de mascarada POSTROUTING. Ați putea să-l înlocuiți cu un singur `iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE`
drapel ng
Am eliminat unul, acum am asta: ``` ip6tables -A INPUT -i eth0 -m tcp -p tcp --dport 25 -j REJECT ip6tables -A INPUT -i eth0 -m tcp -p tcp --dport 2525 -j REJECT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ```
Puncte:2
drapel cl
A.B

Lăsați Docker să se ocupe de redirecționare, care este dinamică și se poate schimba atunci când containerele sunt adăugate, eliminate sau repornite. Dar vezi ACTUALIZAȚI de mai jos.

Această redirecționare nu ar trebui să fie către 172.18.0.1, care este gazda și nu containerul. Când gazda primește o astfel de conexiune, aceasta este gestionată de docker-proxy care îl trimite la container, pierzând adresa IP sursă în acest proces.

Docker deja DNAT + direcționează corect acest port (cu excepția gazdei în sine, unde docker-proxy joacă acest rol) în ultima regulă a setului de reguli, către containerul care rulează cu adresa 172.18.0.2. Cu excepția faptului că este configurat să folosească portul 2525 mai degrabă decât portul 25.

  107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 to:172.18.0.2:25

Acest lucru ar trebui remediat cu setările Docker, nu manual iptables reguli care nu se pot schimba ori de câte ori se modifică aspectul containerului. Deoarece portul 25 este privilegiat, dacă Docker rulează fără root, sunt necesare setări suplimentare, verificați documentație despre expunerea porturilor privilegiate.


ACTUALIZAȚI (luând în considerare comentariile lui OP): OP nu poate fi utilizat în prezent -p 25:25 deoarece docker-proxy se ciocnește cu serverul SMTP al gazdei locale și concurează pentru ascultarea pe portul 25 de pe gazdă. Acesta este motivul inițial (greșit) iptables redirecționarea a fost făcută de OP.

Se poate fie:

  • dezactivați la nivel global docker-proxy prin alergare dockerd cu proprietatea userland-proxy setat la fals

    fie ca a parametru --userland-proxy=false sau ca proprietate „userland-proxy”: fals adăugat la /etc/docker/daemon.json.

    Acest lucru va permite apoi utilizarea docker run ... -p 25:25 ... (la fel de documentat) fără ciocnire: gazda va ajunge la ea însăși când ajunge la localhost sau $HOSTNAME, sistemele la distanță vor ajunge la container și nicio „Adresă deja în uz” nu va face ca demonul SMTP al gazdei sau containerul Docker să eșueze la pornire.

  • sau adăugați o redirecționare manuală (cu o configurare lungă de mai jos pentru a o face aproape automat)

    Ori de câte ori containerul este repornit, există riscul ca adresa sa IP (internă) să se schimbe. Deci acest lucru trebuie calculat. Deci cu un container numit mx folosind o rețea numită mx și o singură adresă IP implicată se poate face așa cum se explică mai jos.

    Creați un lanț de prerouting separat (astfel încât să poată fi șters fără a fi nevoie să spălați nimic altceva) și apelați-l mai întâi:

    iptables -t nat -N mynat
    iptables -t nat -I PREROUTING -j mynat
    

    Adresa IP a containerului poate fi preluată programatic (pentru cazul simplu al unui container numit mx cu o singură adresă):

    containerip=$(docker container inspect --format '{{.NetworkSettings.IPAddress}}' mx)
    

    (sau s-ar putea folosi jq: containerip=$(docker container inspect mx | jq '.[].NetworkSettings.IPAddress')

    Găsirea numelui interfeței bridge-ului este mai complicată, sau cel puțin nu am putut găsi o modalitate pentru aceasta folosind numai docker... inspectați. Deci, găsiți adresa IP pe gazdă și interogați gazda folosind adresa IP pentru a găsi doar interfața bridge unde este setată această adresă IP specifică (necesită jq comanda.)

     bridgeip=$(docker network inspect --format '{{(index .IPAM.Config 0).Gateway}}' mx)
     bridgeinterface=$(adresa ip -json afișată la „$bridgeip”/32 | jq -r '.[].ifname')
    

    Spălați și repopulați mynat de fiecare dată când containerul este (re)pornit:

    iptables -t nat -F mynat
    iptables -t nat -A mynat ! -i "$bridgeinterface" -p tcp --dport 25 -j DNAT --to-destination "$containerip":25
    

    care ar fi pentru cazul actual:

    iptables -t nat -I mynat ! -i br-b147ffdbc9f3 -p tcp --dport 25 -j DNAT --la-destinație 172.18.0.2:25

    Și pentru a vă asigura că propriile reguli de firewall-uri ale lui Docker nu blochează un astfel de trafic, faceți ceva similar începând cu filtru/REDIRECŢIONA de la DOCKER-UTILIZATOR lanţ.

    Inițial (dacă de la boot, ar putea fi necesar să creați mai întâi DOCKER-UTILIZATOR):

    iptables -N myforward
    iptables -I DOCKER-USER 1 -j myforward
    

    Apoi, mai târziu, de fiecare dată când containerul este (re)pornit:

    iptables -F myforward
    iptables -A myforward -p tcp ! -i „$bridgeinterface” -d „$containerip” -p tcp --dport 25 -j ACCEPT
    

    care ar fi pentru cazul actual:

    iptables -A myforward -p tcp ! -i br-b147ffdbc9f3 -d 172.18.0.2 -p tcp --dport 25 -j ACCEPT
    

Note:

  • Pentru a simplifica regulile de mai sus și a evita unele dintre calcule, containerul și rețeaua sa de punte pot fi pornite cu adrese IP fixe.Vedeți, de exemplu, acest SO Q/A: Atribuiți IP static containerului Docker.

  • Iată, de asemenea, un Q/A UL SE cu un răspuns de-al meu despre problemele la interacțiunea cu Docker (este conceput pentru nftables dar unele părți despre DOCKER-UTILIZATOR lanț sau br_netfilter interacțiunile bridge sunt încă de interes): docker pentru lista albă nftables

drapel ng
Mulțumiri. Aceasta folosește `docker run`: `docker run -d -P --network mx -p 2525:25 -v /srv/mx/:/mx/ --restart always --name mx mx`
drapel ng
Rulez pe portul 2525 pentru că, dacă nu rulez un postfix pe localhost, comanda `mail` nu funcționează și e-mailul nu este livrat. https://pastebin.com/RR2mDx9T (când rulați containerul pe portul 25)
eKKiM avatar
drapel lr
afaik docker userland proxy va literalmente proxy conexiunea, astfel IP-ul sursei va fi schimbat..
A.B avatar
drapel cl
A.B
@eKKiM într-adevăr, asta e ceea ce mă refer la `docker-proxy`.
A.B avatar
drapel cl
A.B
@Tuinslak, deci cu acest context (nu se poate folosi portul 25) regula Docker deja existentă (ultima regulă văzută în setul de reguli afișată în întrebarea pusă în aplicare de `-p 2525:25`) o gestionează deja. De ce adaugi atunci o regulă care o înlocuiește?
eKKiM avatar
drapel lr
@A.B formularea „Lasă doar pe Docker să se ocupe de redirecționare” permiteți-mi să presupun că o las să fie gestionată de docker-proxy
A.B avatar
drapel cl
A.B
@eKKiM docker-proxy este implicat numai pentru cazul gazdă: 172.18.0.1. Nu este implicat la rutarea către containerul 172.18.0.2. Dar regula iptables OP adăugată face ca fluxul să fie forțat la docker-proxy în loc să fie direcționat.
drapel ng
Dacă nu rulez `iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE`, serverul nu redirecționează pachete și nu îl pot folosi ca VPN/ping nicio gazdă din afara serverului - https:// pastebin.com/uY0Rka6Z
drapel ng
Se pare că `iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.2:25` funcționează. Deci, nu pot folosi docker-proxy (`172.18.0.1`), dar trebuie să folosesc IP-ul real al containerului?
A.B avatar
drapel cl
A.B
Linkul meu despre `docker-proxy` spune că poate fi dezactivat global cu `--userland-proxy=false`. Sau `"userland-proxy": false` în [`/etc/docker/daemon.json`](https://docs.docker.com/engine/reference/commandline/dockerd/) . Dacă nu aveți nevoie să ajungeți la containerele dvs. (toate nu doar la acesta: este global) folosind gazda în sine, atunci ar trebui să puteți utiliza pur și simplu `-p 25:25`.Aceasta este o problemă numai atunci când este implicat ac NAT, deci atunci când un container trebuie să ajungă la un alt container folosind adresa IP a gazdei publice (adresa eth0).
A.B avatar
drapel cl
A.B
Puteți folosi `172.18.0.2:25` fără probleme, dar rețineți că această adresă nu este permanentă, se poate schimba atunci când rulați alte containere, în funcție de configurație.
A.B avatar
drapel cl
A.B
Mi-am modificat răspunsul pentru a aborda informațiile din comentarii și a face ceva automatizare.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.