[workaround] routing furcsaság: tcp megy, udp nem

Sziasztok,

eddig nem sikerült megoldást találnom:

van ket interface; az openvpn és az asterisk forgalmát az egyik, minden mást a másik interface irányába szeretnék terelni; főszereplőnk a második interface: enp0s3 

A felállás:

  • xxx.xxx.xxx.xxx a destination ip
  • t1 a tabla, amire illeszkedik a rule
  • enp3s0 a gonosz interface
  • !gonosz interface ( enp0s31f6 )

A routing tábla így fest:

default via 192.168.1.254 dev enp0s31f6 onlink 
xxx.xxx.xxx.0/24 dev enp3s0 proto kernel scope link src xxx.xxx.xxx.xxx 
192.168.1.0/24 dev enp0s31f6 proto kernel scope link src 192.168.1.220 

A t1 tábla routingja így néz ki 
default via xxx.xxx.xxx.1 dev enp3s0

A hozzá tartozó rule ez:

32765:  from xxx.xxx.xxx.xxx lookup t1

 

Minden tcp forgalom rendben lezajlik, azonban ha udp protokollt használok, a következő történik:

Nem hallgat semmi szerveroldalon, kliensoldalon 

echo retek |nc -v -u xxx.xxx.xxx.xxx 1194
xxx.xxx.xxx.xxx 1194 (openvpn) open

tcpdump ekkor:

16:21:23.336886 IP 192.168.3.109.44784 > xxx.xxx.xxx.xxx.1194: UDP, length 6
16:21:23.358430 IP xxx.xxx.xxx.xxx > 192.168.3.109: ICMP xxx.xxx.xxx.xxx udp port 1194 unreachable, length 42

azoonban, ha a másik oldalon szintén hallgat a netcat, akkor:

16:21:34.297789 IP 192.168.3.109.56841 > xxx.xxx.xxx.xxx.1194: UDP, length 6

...és ekkor a !gonosz interface -n megy a válasz.

Vontakozó iptables szabályok:

-A INPUT -i enp3s0 -p udp -m udp --dport 1194 -j ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i enp3s0 -j REJECT --reject-with icmp-port-unreachable
-A POSTROUTING -o enp3s0 -j MASQUERADE
-A POSTROUTING -o enp3s0 -j SNAT --to-source xxx.xxx.xxx.xxx

Az utóbbi kettővel működik/működött az asterisk, de az ezek szerint csak azért, mert a szolgáltató irányába erre az interface-re direkt routing volt beállítva. Mivel ezt kiszedtem, az udp miatt az asterisk is rossz interface -n válaszol, magyarul protokoll és nem szolgáltatásfüggő  a probléma.

Őszintén szólva: lövésem sincs, mi okozhatja ezt. Ha tudnátok némi világosságot hozni a dologba, azt megköszönném, én elakadtam :)

 

Update1

Reverse path filtering b..szkurálása sem segített

dmesg -ben semmi nyoma problémának.

 

Update2:

tcp -vel workaroundolok, hatha.

Hozzászólások

Szerkesztve: 2020. 08. 08., szo - 19:09

Szia!

enp0s31f6 -> eth0 ( Minden ami nem OpenVPN és nem Asterisk )
enp3s0 -> eth1 ( OpenVPN + Asterisk )

eth0 -> 192.168.1.220 gw 192.168.1.254
eth1 -> xxx.xxx.xxx.0/24

Asterisk paraméterei? (melyik hoston fut, ha külön host - mi a ip/subnet/gw címe?)
OpenVPN paraméterei? (melyik hoston fut, ha külön host - mi a ip/subnet/gw címe?)

Iptables szabály hiányos ha fenti paraméterek világosak utána lehet megírni a NAT táblát is

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
#
#
#
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
#
#
#
-A INPUT -i lo -j ACCEPT
#
#
#
# eth0 - uplink #
#
-A INPUT -i eth0 -s 0.0.0.0/8 -j DROP
-A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
-A INPUT -i eth0 -s 100.64.0.0/10 -j DROP
-A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
-A INPUT -i eth0 -s 169.254.0.0/16 -j DROP
-A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
-A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
-A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
#
-A INPUT -i eth0 -d 0.0.0.0/8 -j DROP
-A INPUT -i eth0 -d 10.0.0.0/8 -j DROP
-A INPUT -i eth0 -d 100.64.0.0/10 -j DROP
-A INPUT -i eth0 -d 127.0.0.0/8 -j DROP
-A INPUT -i eth0 -d 169.254.0.0/16 -j DROP
-A INPUT -i eth0 -d 172.16.0.0/12 -j DROP
-A INPUT -i eth0 -d 192.168.1.0/24 -j ACCEPT
-A INPUT -i eth0 -d 192.168.0.0/16 -j DROP
#
##-A INPUT -i eth0 -j DROP
#
#
#
# eth1 - LAN? #
#
-A INPUT -i eth1 -s 0.0.0.0/8 -j DROP
-A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
-A INPUT -i eth1 -s 100.64.0.0/10 -j DROP
-A INPUT -i eth1 -s 127.0.0.0/8 -j DROP
-A INPUT -i eth1 -s 169.254.0.0/16 -j DROP
-A INPUT -i eth1 -s 172.16.0.0/12 -j DROP
-A INPUT -i eth1 -s 192.168.0.0/16 -j DROP
-A INPUT -i eth1 -s xxx.xxx.xxx.0/24 -j ACCEPT
#
-A INPUT -i eth1 -d 0.0.0.0/8 -j DROP
-A INPUT -i eth1 -d 10.0.0.0/8 -j DROP
-A INPUT -i eth1 -d 100.64.0.0/10 -j DROP
-A INPUT -i eth1 -d 127.0.0.0/8 -j DROP
-A INPUT -i eth1 -d 169.254.0.0/16 -j DROP
-A INPUT -i eth1 -d 172.16.0.0/12 -j DROP
-A INPUT -i eth1 -d 192.168.0.0/16 -j DROP
-A INPUT -i eth1 -d xxx.xxx.xxx.0/24 -j ACCEPT
#
##-A INPUT -i eth1 -j DROP
#
#
#
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#
#
#
# eth0 #
#
-A INPUT -i eth0 -p udp -m udp --dport 1194 -j ACCEPT
#
#
#
-A INPUT -j DROP
#
#
#
-A FORWARD -j DROP
#
#
#
-A OUTPUT -o lo -j ACCEPT
#
#
#
# eth0 - uplink #
#
-A OUTPUT -o eth0 -s 0.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -s 10.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -s 100.64.0.0/10 -j DROP
-A OUTPUT -o eth0 -s 127.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -s 169.254.0.0/16 -j DROP
-A OUTPUT -o eth0 -s 172.16.0.0/12 -j DROP
-A OUTPUT -o eth0 -s 192.168.1.0/24 -j ACCEPT
-A OUTPUT -o eth0 -s 192.168.0.0/16 -j DROP
#
-A OUTPUT -o eth0 -d 0.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -d 10.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -d 100.64.0.0/10 -j DROP
-A OUTPUT -o eth0 -d 127.0.0.0/8 -j DROP
-A OUTPUT -o eth0 -d 169.254.0.0/16 -j DROP
-A OUTPUT -o eth0 -d 172.16.0.0/12 -j DROP
-A OUTPUT -o eth0 -d 192.168.1.0/24 -j ACCEPT
-A OUTPUT -o eth0 -d 192.168.0.0/16 -j DROP
#
-A OUTPUT -o eth0 -j DROP
#
#
#
# eth1 - LAN? #
#
-A OUTPUT -o eth1 -s 0.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -s 10.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -s 100.64.0.0/10 -j DROP
-A OUTPUT -o eth1 -s 127.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -s 169.254.0.0/16 -j DROP
-A OUTPUT -o eth1 -s 172.16.0.0/12 -j DROP
-A OUTPUT -o eth1 -s 192.168.0.0/16 -j DROP
-A OUTPUT -o eth1 -s xxx.xxx.xxx.0/24 -j ACCEPT
#
-A OUTPUT -o eth1 -d 0.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -d 10.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -d 100.64.0.0/10 -j DROP
-A OUTPUT -o eth1 -d 127.0.0.0/8 -j DROP
-A OUTPUT -o eth1 -d 169.254.0.0/16 -j DROP
-A OUTPUT -o eth1 -d 172.16.0.0/12 -j DROP
-A OUTPUT -o eth1 -d 192.168.0.0/16 -j DROP
-A OUTPUT -o eth1 -d xxx.xxx.xxx.0/24 -j ACCEPT
#
-A OUTPUT -o eth1 -j DROP
#
#
#
-A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
#
#
#
-A OUTPUT -j DROP
#
#
#
COMMIT

Az az igazsag, hogy ezeket nyilvan nem mind oszthatom meg,

Azonban: a jekenlegi iptables szabalyok alapjan az INPUT es az OUTPUT chain is rendben vannak. Az asterisk explicit megadott target network based routinggal szinten jo. Ugyszinten jo az openvpn is, amennyiben a routing szintjen explicit meghatarozom, hogy az output a kliens iranyaba az adott interface -on menjen MINDEN forgalom.

tcp -n egyaltalan nincs ilyen baj.

Magyarul: itt a routing lesz a hunyo, ha jol tippelem.

Error: nmcli terminated by signal Félbeszakítás (2)

Ránézésre azon sok néznivaló nincs:

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i enp3s0 -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -i tun0 -j ACCEPT
-A INPUT -p tcp -m tcp --dport sshport -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s 192.168.1.0/24 -i enp0s31f6 -j ACCEPT
-A INPUT -s vo.ip.provi.der/24 -i enp0s31f6 -j ACCEPT
-A INPUT -s 10.0.0.0/8 -i enp0s31f6 -j ACCEPT
-A INPUT -s vo.ip.provi.der/24 -i enp3s0 -j ACCEPT
-A INPUT -i enp3s0 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i enp0s31f6 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i tun0 -o enp0s31f6 -j ACCEPT
-A FORWARD -i enp0s31f6 -o tun0 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-port-unreachable

-A POSTROUTING -s 192.168.30.0/24 -o enp0s31f6 -j MASQUERADE
-A POSTROUTING -o enp3s0 -j MASQUERADE
-A POSTROUTING -o enp3s0 -j SNAT --to-source xxx.xxx.xxx.xxx

 

Továbbá, ahogy írtam is: ha explicit társítom a kimenő forgalmazás target networkjét a t1 táblához, akkor voilá - működik. Ez alapján a tűzfalnak nem igazán hinném, hogy ehhez köze volna. Így tud oob működni az asterisk is; emellé kellett most beheggesztenem az openvpn -t, aminél előjött a turpisság.

Error: nmcli terminated by signal Félbeszakítás (2)

Ha rám hallgatsz, akkor az INPUT sorrendjét így változtatod meg:

 

-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i enp3s0 -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -i tun0 -j ACCEPT
-A INPUT -p tcp -m tcp --dport sshport -j ACCEPT

Debian Linux rulez... :D
RIP Ian Murdock

A tcpdump szerint az input rendben eljutott az openvpn -ig; a logok is erre utalnak, illetve a fenti netcat teszt eredmenye is erre utal (tuloldalon megjelent a becatolt string), de udp eseten mas iranyba kodorogtak vissza a csomagok (ugye lezart portnal ICMP valasz ment vissza, szinten a megfelelo interface -on) :) Ha explicit megadtam a kliens ip -t a routingban, akkor termeszetesen visszatalalt. Valamiert tehat a tcp -n mukodo routing policy nem mukodott udp -n. Erre javasoltak par helyen az rp_filter bizgeralasat, de nem jutottam vele elorebb.

Error: nmcli terminated by signal Félbeszakítás (2)

Szia

Amit meg akarsz valósítani azt PBR (Policy Based Routing) és/vagy VRF (Virtual Routing and Forwarding)-nek hívják, de inkább neked a VRF kellene.
Mivel ezek egyike sincs implementálva Linux alatt - hiába hivatkoznak rá az rohadtul nem az.
Szerintem az lenne az egyszerűbb megoldás ha külön 2db Virtuális gépet (VM) csinálnál:

VM-1: OpenVPN + Asterisk - 2db hálókártya: egyik a szolgáltatások felé (ez a kliensek GW -címe), másik az uplink ami a VM-ben a GW-ip.
VM-2: Minden más - 2db hálókártya: egyik a szolgáltatások felé (ez a kliensek GW -címe), másik az uplink ami a VM-ben a GW-ip.

Linux féle "PBR/VRF"-ről itt van egy remek összefoglaló leírás:
https://cumulusnetworks.com/blog/vrf-for-linux/

 

Nézd meg ezeket hátha segít:

/etc/network/interfaces
------------------------------------------------------------------------------
allow hot-plug enp0s3
..
pre-up ethtool -K enp0s rx off tx off sg off tso off gso off gro off ufo off lro off

allow hot-plug enp0s31f6
...
pre-up ethtool -K enp0s31f6 rx off tx off sg off tso off gso off gro off ufo off lro off
------------------------------------------------------------------------------

/etc/sysctl.conf
------------------------------------------------------------------------------

# net.ipv4.ip_forward_use_pmtu = 0
net.ipv4.ip_no_pmtu_disc = 1

net.ipv4.ip_forward = 1

net-ipv4.ip_local_port_range = 32768 65535

net.ipv4.conf.enp0s3.forwarding = 1
net.ipv4.conf.enp0s3.mc_forwarding = 0
net.ipv4.conf.enp0s3.rp_filter = 2
net.ipv4.conf.enp0s3.arp_filter = 1
net.ipv4.conf.enp0s3.proxy_arp = 1
net.ipv4.conf.enp0s3.proxy_arp_pvlan = 1
net.ipv4.conf.enp0s3.send_redirects = 0
net.ipv4.conf.enp0s3.accept_redirects = 0
net.ipv4.conf.enp0s3.secure_redirects = 1
net.ipv4.conf.enp0s3.accept_source_route = 0
#
net.ipv4.conf.enp0s31f6.forwarding = 1
net.ipv4.conf.enp0s31f6.mc_forwarding = 0
net.ipv4.conf.enp0s31f6.rp_filter = 2
net.ipv4.conf.enp0s31f6.arp_filter = 1
net.ipv4.conf.enp0s31f6.proxy_arp = 1
net.ipv4.conf.enp0s31f6.proxy_arp_pvlan = 1
net.ipv4.conf.enp0s31f6.send_redirects = 0
net.ipv4.conf.enp0s31f6.accept_redirects = 0
net.ipv4.conf.enp0s31f6.secure_redirects = 1
net.ipv4.conf.enp0s31f6.accept_source_route = 0

------------------------------------------------------------------------------

ami nekem furcsa az a -j MASQUERADE -t követő -j SNAT. a MASQUERADE az termináló rule, tehát ott az SNAT-os szabályt sose éri el elvileg.

ami még meg szokott viccelni nat-os szabályok álligatásakor, az az hogy a conntrack táblába egy korábbi iptables konfigurációból "beragadnak" connectionök, amiket később már nem vagy nem úgy nell natolni, pl. kiveszel egy SNAT/DNAT/MASQUERADE szabályt vagy --to-ports opciót átállítasz. ilyenkor - ugyan nem kisérleteztem ki - de nekem úgy tűnt mintha nem venné figyelembe a változott iptables szabályokat, amikor korábbi konfig idején kelt forgalmat natolja. "conntrack -F" segíthet ilyenkor.

 

service alapú routingot én fwmark-kal szoktam csinálni:

ha az asterisk és az openvpn helyben futnak, akkor 

- -t nat -A OUTPUT -p udp --sport 1194 -j MARK --or-mark 0x01  # 1. bit megjelölése az openvpn által küldött packetokon
- -t nat -A OUTPUT -m owner --uid-owner asterisk -j MARK --or-mark 0x01  # az asterisk forgalmát nem lehet egyetlen porttal meghatározni, úgyhogy inkább local user uid alapján fognám meg
- ip rule add fwmark 0x01/0x01 lookup $table_id  # ha a bit 1 be van jelölve, használja ezt a route táblát
- ip route add 0.0.0.0/0 via $gw dev $iface table $table_id  # gateway és kimenő interface beállítása a spéci route táblán

ha az asterisk nem azon a gépen fut, ahol a tűzfal+routing lokiga működik, akkor lehetne 3 lépésben megfogni:

- --uid-owner plusz -j MARK-kal megjelölni az asteriskes packetokat OUTPUT chain-ben
- -m mark --mark 0x01/0x01 plusz -j SNAT -tal a megjelölt packetokat egy dedikált source IP-ről küldeni (POSTROUTING-nál nem lehet az owner modult használni, ezért kell a mark-kal átadni az infót)
- a router gépen simán "-s" source IP alapján routolni, mint fent.

az openvpn mivel mindig egy porton beszél, a routeren is el lehet különíteni a forgalmát.

Valoszinuleg itt van/lenne a kutya elasva. Mindazonaltal most atalltam openvpn eseteben tcp -re, kivancsi vagyok, mennyire lesz megbizhato. Nyilvan ez egy workaround, nem is a legszebb fajtabol, de -ismered a kozeget- nem sok lehetosegem van a kiserletezesre, kovetkezo hetveget meg mar nem akartam bealdozni. (Hacsak az openvpn-over-tcp nem allit olyan kihivasok ele, amiket le kell gyurnom)

A MASQUERADE -val kapcsolatban igazad vala, anno sokszor felhivtad ra a figyelmemet, itt megis ignoraltam azt, hogy az SNAT szabalyok MASQUERADE utan mar soha nem fognak ervenyesulni (elmeletileg).

Error: nmcli terminated by signal Félbeszakítás (2)

Van egy masik is, amit a fejlesztok hasznalnak, az UDP -n fut; itt szerencsere nem igazan van/lehet forgalom; a workaroundra azonban szukseg volt nagy hirtelen. A ket VPN -t viszont nem szeretnem osszevonni, ezert a felmegoldas.

Error: nmcli terminated by signal Félbeszakítás (2)

asterisknél még gondot okozhat, hogy a sip protokollban (vagy rtp?) van olyan hogy "hova kérem a válasz forgalmat". tehát ami stream-et az asterisknek meg kell kapni, az nem feltétlenül a tőle származó udp forgalomra adott válasz lesz, hanem a firewall szemszögéből egy kívülről érkező connection nyitás. valahol lehet konfigolni az asteriskben hogy mit hazudjon saját külső IP-jének, ahova a bejövő (válasz) forgalmat várja. van asszem az nf_nat_sip vagy nf_conntrack_sip modul, ami belenéz az áthaladó sip forgalomba és észreveszi az ilyen "ide és erre a portra kérem a bejövő RTP stream-et" tipusú üzenetet, amit az asterisk küld és ez alapján az iptables -m state --state RELATED szabály talán illeszkedni fog, tehát gyakorlatilag dinamikusan kinyitja neked a portot. de ebbe én sose mertem belemenni, mert ki tudja, mennyire up-to-date a conntrack sip modul, jól érti-e a protokollt... ki tudja... bármilyen titkosítás be van állítva akkor semmi haszna. ezért inkább kinyitottam az internetfelől natoltam egy udp port range-t egy az egyben az asterisk felé, az asterisknek meg megadtam h ezt a port range-t használhatja. ilyenkor jó ha dedikált külső IP-je van az voip-nek, máskülönben figyelni kell h arra a range-ra ne legyen PAT-olás más gépekről a belső hálón.

SIP-hez érdemes a helpert használni...

Valahogy így:

iptables -t raw -F
iptables -t raw -X

rmmod nf_nat_sip
rmmod nf_conntrack_sip
modprobe nf_conntrack_sip ports=5060 sip_direct_signalling=0 sip_direct_media=0
modprobe nf_nat_sip

iptables -t raw -A PREROUTING -j CT -i ${BE_IF} -p udp -s ${SIP_HOST} --dport 5060 --helper sip
iptables -t raw -A PREROUTING -j CT -i ${KI_IF} -p udp -d ${SIP_HOST} --dport 5060 --helper sip

Debian Linux rulez... :D
RIP Ian Murdock

igen már jobban emlékszem, SIP forgalom is jön "kéretlenül", de az mindig csak egy porton, tehát portszám alapján lehet azonosítani (és natolni vagy routolni ahogyan az ember akarja). itt nem tudom akkor miben segít a helper. ha jön be egy RTP stream azt így se tudja a router hova tenni. nem?

SIP az a VoIP signaling protokoll. Általában TCP/5060 vagy UDP/5060 esetleg titkosított TLS/5061. Abban beszéli meg a 2 végpont, hogy a tényleges RTP/UDP média milyen dinamikus high-range kb. 40.000-65.000 tartományban küldjön-fogadjon. Ha nem TLS titkosított a SIP, akkor a helper ki tudja lesni a SIP csomag belsejében a megfelelő "CONTACT" mező IP-cím + port párosait, és át tudja írni a NAT-olt belső címet a publikus WAN címre, így a válasz-csomagok visszatalálnak + a tűzfal is beengedi.

ami még meg szokott viccelni nat-os szabályok álligatásakor, az az hogy a conntrack táblába egy korábbi iptables konfigurációból "beragadnak" connectionök, amiket később már nem vagy nem úgy nell natolni, pl. kiveszel egy SNAT/DNAT/MASQUERADE szabályt vagy --to-ports opciót átállítasz. ilyenkor - ugyan nem kisérleteztem ki - de nekem úgy tűnt mintha nem venné figyelembe a változott iptables szabályokat, amikor korábbi konfig idején kelt forgalmat natolja. "conntrack -F" segíthet ilyenkor.

Ez csak azért van, mert a kernel egy kapcsolathoz csak egyszer nézi meg a NAT táblát... Onnantól már élő kapcsolat van, nem kell újból végigjárni feleslegesen...

Debian Linux rulez... :D
RIP Ian Murdock