Add package fff-layer3-ipv4snat #26
No reviewers
Labels
No Label
RFC
RFT
WIP
blocked
bsp
bug
build/scripts/tools
duplicate
feature
fixed
layer3
mantis
more details required
needs changes
node
packages/fff
rejected
security
trivial
upstream
No Milestone
No Assignees
4 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: freifunk-franken/firmware#26
Loading…
Reference in New Issue
No description provided.
Delete Branch "ChristianD/firmware:ipv4snat"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
With this package it is possible to make SNAT with IPv4 on the router
The user must set a peer_ip setting in gateway.meta.peer_ip to get a single ip for peering interfaces.
At ipaddr the user must set a ip that not use in babel (e.g. 192.168.0.1/16) for the clients
With this package the ipaddr address is SNAT to the peer_ip and every router need only one
freifunk ip and can use the same ipaddr on every router.
It is a system like cgnat from big provider
Signed-off-by: Christian Dresel freifunk@dresel.systems
@ -0,0 +13,4 @@
TITLE:=Freifunk-Franken layer3 configuration with nat
URL:=https://www.freifunk-franken.de
DEPENDS:= \
+iptables-mod-nat-extra \
braucht es das? Wenn ich opkg frage:
Aber du verwendest SNAT und machst kein NETMAP.
ohne dem funktioniert kein SNAT, probiere mal mit der aktuellen Firmware ein SNAT:
root@fff-gw-cd-home:~# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 192.168.0.1
iptables v1.8.3 (legacy): unknown option "--to-source"
Try `iptables -h' or 'iptables --help' for more information.
mit diesem Ding tut es dann einwandfrei
Hi, kannst du auch zu machen. Das macht OpenWrt einfach so. Die haben sich scheinbar das libipt_SNAT einfach weggespart und man muss das obige nehmen. Das bringt libipt_NETMAP mit. Und das kann das auch plus NETMAP
@ -0,0 +7,4 @@
# Check if NAT is set
# If NAT is set
if uci -q get gateway.@client[0].nat; then
Da kommt die Frage auf, was ist mit @client[n]?
das ist bisher nicht vorgesehen und überall so gebaut, daher habe ich das auch erstmal so weiter übernommen. Will man mal ein @client[n] haben muss man das hier mit anpassen
Ich fände es schon gut, wenn man bei einem zweiten Clientnetz auch nat einschalten koennte. Oder eins ohne und das andere mit. usw.
Ich glaube aktuell funktioniert technisch noch gar kein 2. Clientnetz (Interface anlegen und Kram fehlt da alles). Daher kann man da auch noch kein SNAT einschalten wenn kein 2. Client funktioniert.
Korrigiert mich wenn ich falsch liege
@ -0,0 +16,4 @@
# first we flush the table
iptables -t nat --flush
# and load the new settings
iptables -t nat -A POSTROUTING -s $ipaddr -j SNAT --to-source $peer_ip
-s $ipaddr matcht doch nur die IP des Routers. Moechte man nicht das clientnetz natten? Also hier die Netzwerkadresse/mask eintragen.
Im Wiki steht gateway.@client[0].ipaddr als Type "list" drin. Was passiert, wenn da mal mehrere vorhanden sind?
in $ipaddr steht das Netz, was an br-client gehangen wird:
ipaddr=$(uci get gateway.@client[0].ipaddr); then
also z.b. 192.168.0.1/16
root@testknoten:~# uci get gateway.@client[0].ipaddr
192.168.0.1/16
in $peer_ip steht die IP Adresse die per Babel ins Freifunk announced wird und worauf geNATet wird:
if ! peer_ip=$(uci get gateway.meta.peer_ip); then
also z.b. 10.50.169.106 (ohne Subnetzmaske, es handelt sich aber um ein /32)
root@testknoten:~# uci get gateway.meta.peer_ip
10.50.169.106
Demnach NATet das iptables das gesamte 192.168.0.1/16 auf 10.50.169.106
Die eiinzige Frage die ich mir gerade stelle, eigentlicbh wäre 192.168.0.0/16 ich vermute aber mal das dies iptables egal ist. 192.168.0.0/16 kann ich aber nicht als gateway.@client[0].ipaddr eintragen, da dies genauso wie es dort steht an br-client gehangen wird.
Hier mal meine Beispielrouterkonfiguration und wie es auf dem Interfaces aussieht (eth0.3 ist das Babel Peering Interface):
und jetzt bei der iptables Ausgabe sieht man, das iptables das auch richtig macht und wenn es ein 192.168.0.1/16 bekommt, einfach das richtige 192.168.0.0/16 einträgt, so wie ich es erwartet habe
Tatsächlich steht im Wiki ipaddr als list drinnen, das macht aber in meinen Augen keinen Sinn und wie man bei meinen Beispiel sieht nutze ich eigentlich auch generell option für ipv4.
Ich bin dafür das zu ändern.
Danke, wieder was gelernt.
Du kannst hier zu machen.
Das mit der ipaddr als list sollte man vielleicht noch mal in die Runde fragen.
@ -0,0 +3,4 @@
PKG_NAME:=fff-ipv4snat
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/fff-ipv4snat
PKG_BUILD_DIR kann weg, ist default.
Was ist SNAT?
Ich würde fff-ipv4-snat als Name bevorzugen. Generell könnte man noch ein bisschen mehr schwafeln, was das Package dann tun soll (für die Commit-Message; zur Not auf Deutsch und ich übersetze es dir ;-))
Ich könnte dir jetzt Textteile kopiere aber... Reicht das auch so?
https://www.itwissen.info/SNAT-source-NAT.html
Grundsätzlich das gleiche NAT wie du es bei deinen Heimrouter kennst, nur das hier auf eine fixe IP Adresse (der RouterIP) geNATet wird und nicht wie bei masquerade auf die IP die gerade aktuell auf einem Interface liegt.
Wie wäre es mit fff-layer3-ipv4snat ? Immerhin ist das eine layer3 Erweiterung?
Ich überlege mal ;)
23b89ca465
tobaedc4ae60
Diverse Kleinigkeiten überarbeitet:
noch offen:
Weiß nicht, ob wir diesen Weg gehen sollten. Nur weil wir es gerade "nur" für layer3 implementiert haben ist es ja per se keine layer-3-spezifische Funktion? Ich würde eher bei fff-ipv4-snat bleiben, oder ggf. fff-snat-ipv4, weil eigentlich ersteres die Funktion ist, und ipv4 die "Variante"?
@ -0,0 +8,4 @@
define Package/fff-ipv4snat
SECTION:=base
CATEGORY:=Freifunk
TITLE:=Freifunk-Franken layer3 configuration with nat
nat->snat?
Entweder überall SNAT oder es ist nicht so wichtig und wir nehmen überall NAT ...
ja sollte man wohl ändern, mach ich beim nächsten Update mit
für die Node Firmware macht das ganze absolut gar keinen Sinn. Ich finde schon das es eine Layer 3 spezielle Funktion ist, die auch nur mit der +fff-layer3-config funktioniert (daher die Abhängigkeit dorthin). Ich hab sogar anfangs überlegt das Script einfach in fff-layer3-config abzulegen ohne eigenes package. Der Grund warum ich mich dagegen entschieden habe war, wenn jemand absolut kein NAT möchte weil er der Meinung ist das dies absolut gegen Freifunkprinzipien ist, kann er das Paket abwählen oder auch wenn die Community/Entwickler sagen, wir wollen das keinesfalls in der offiziellen Firmware, dann kann ich das für mich als extra Paket einfach mit anwählen beim bauen.
Schlussendlich ist es mir aber eigentlich wirklich egal, ich will da jetzt auch nicht ewig deshalb diskutieren, sag was dir am besten gefällt dann machen wir es so ;)
fff-layer3-ipv4snat ist doch ok, da es "nur" eine Erweiterung vom configure
gatewayl3-config ist.baedc4ae60
to7c9b8d03f5
Ich hab das package jetzt mal nach fff-layer3-ipv4snat unbenannt und auch alle NAT in SNAT unbenannt damit es gleich ist.
Add package fff-ipv4snatto Add package fff-layer3-ipv4snatAn sich gefällt mir die Idee, an der Implementierung müssen wir aber noch etwas feilen. So wie es jetzt ist, ist mir das ganze deutlich zu anfällig bei späteren Änderungen kaputt zu gehen.
@ -0,0 +4,4 @@
# If NAT is set
if uci -q get gateway.@client[0].nat; then
if ! peer_ip=$(uci get gateway.meta.peer_ip); then
echo "WARNING: No peer_ip set! For NAT you must set a peer_ip"
Wenn ein Feature konfiguriert ist, was mit der aktuellen Konfiguration nicht umsetzbar ist, unbedingt mit Fehler beenden, damit die Konfiguration nicht fertig läuft.
Außerdem dann "ERROR: " statt "WARNING: "
@ -0,0 +14,4 @@
# configure-layer3 -t - reload set the iptables rule not rebootsafe
reload() {
# first we flush the table
iptables -t nat --flush
Die ganze Tabelle zu flushen ist für mich hier ein no-go. Damit flusht man sich potentiell sehr viel mehr weg, als man eigentlich möchte. Das explodiert, wenn man auch nur eine andere Sache in die nat-Tabelle eintragen möchte.
Entweder wir finden einen Weg die Regel wieder sauber zu finden, oder wir starten die ganze Firewall neu, so dass alle Regeln nochmal sauber angewendet werden - war mir eigentlich viel lieber wäre. Ggf. muss man hier noch die Firewall anpassen.
Vorsicht: Die Schnittstelle unserer Firewall gibt aktuell eigentlich kein apply-before-safe her. Da müsste man wohl noch was bauen, z.B. dass die Firewall noch Zeug aus /tmp included, was nach Reboot weg ist. Vielleicht lohnt es sich hier mal zu gucken wie uci das macht.
Prinzipiell gebe ich dir erstmal recht, flush ist unschön.
Anderseits muss ich aber sicherstellen, das nicht irgendeine rule dabei steht die meine rule unbrauchbar macht sonst funktioniert im worst case das ganze Paket hier nicht. Man könnte also sagen der flush ist nötig damit ich einen sicheren Ausgangszustand habe. Vermutlich ist aber auch hier flush wieder der falsche Weg.
Beim OpenWRT werden die uci firewall in /etc/config/network geschrieben allerdings ist dafür ein firewall Paket nötig das wir nicht haben (glaube ich zumindest, müsste ich jetzt nochmal gucken).
Die ganze Firewall neu starten ist vielleicht keine schlechte Idee, darüber denke ich mal nach vllt. kann man da was brauchbares draus machen.
Dein apply-bevor-safe "Problem" verstehe ich gerade nicht.
Wenn du die Firewallregeln schon beim Test anlegst (configuregateway -t), dann ist die Firewallregeln schon rebootsicher abgelegt. Alle anderen Einstellungen gehen verloren, wenn man kein commit macht und dann rebootet.
Daher müsste man die Firewall so erweitern, dass diese auch irgendwoher nicht-persistente Regeln lesen kann. Beispielsweise aus der Ramdisk, also /tmp.
@ -0,0 +27,4 @@
iptables -t nat --flush
rm -rf /usr/lib/firewall.d/30-NAT
for ip in $ipaddr; do
iptables -t nat -A POSTROUTING -s $ip -j SNAT --to-source $peer_ip
reload() wird automatisch auch nach einem apply() aufgerufen. Hier gehört also nur rein, was tatsächlich das "applien" betrifft.
Hm ich stolpere hier gerade drüber:
Wenn ich Testmode verwende, will ich die rule nur in /tmp haben also muss in reload() ein:
echo "iptables -t nat -A POSTROUTING -s $ip -j SNAT --to-source $peer_ip" >> /tmp/firewall.d/30-NAT
rein.
in applien soll die rule nach /usr/lib/firewall.d/30-NAT einfügen, da danach aber wieder ein reload() aufgerufen wird, ist sie automatisch auch wieder im /tmp drinnen und damit doppelt vorhanden wenn man die Firewall neu startet. Irgendwie mäh oder überseh ich etwas?
Vielleicht erledigt sich das aber damit #26 (comment)
Ich werde erstmal die uci Idee weiter verfolgen bevor ich nochmal an /tmp bastel
@ -0,0 +2,4 @@
# Check if NAT is set
# If NAT is set
if uci -q get gateway.@client[0].nat; then
Mir gefällt die Hierarchie-Änderung hier nicht. Ich fände es wesentlich schöner, wenn man innerhalb der Funktionen Bedingungen ansetzt als die Funktionen anhand einer Bedingung zu definieren.
Geb ich dir mittlerweile recht, ich denke auch das umzudrehen ist besser. Ist in Arbeit
Hi Christian,
irgendwie zwickt sich das alles. Ich denke es liegt daran, dass eine iptables rule via uci konfiguriert werden soll. Sowas haben wir noch nicht. Du hast versucht den uci-Mechanismus mit set-revert-commit usw. irgendwie nachzubauen. Darum auch das flushen und direktes Schreiben der ruls im Skript. Das hat da echt nix verloren.
Besser waere es doch, wenn die rules grundsaetzlich in Abhaengigkeit von uci-Eintraegen gesetzt/konfiguriert wird. Also in /usr/lib/firewall.d/30-NAT sowas:
uci get gateway.@client[$n].nat && iptables -t nat -A POSTROUTING ....
Und im33-snat.conf
Skript machst du wie gewohnt nur die uci-Settings. Damit hat man auch den set-revert-commit Mechanismus, und muss nicht mit Files in /tmp rum machen.Und am Schluss immer ein /etc/init.d/firewall start.
Es gibt auch schon einen
procd_add_reload_trigger "fff-firewall"
im init-Skript. Ob es sich lohnt, wegen der einen nat-Zeile damit was zu machen, kann ich auf die Schnelle nicht sagen.Ps. Du hast sicher das
[$n]
bemerkt. Ich lass nicht locker ;-)Hallo Robert
Die Idee ist grundsätzlich gar nicht schlecht aber:
Da komme ich gerade nicht ganz mit, die uci get gateway... ist ja etwas, was der User schreibt. Wohin mach ich dann mein set-revert-commit Zeug? Ich brauch da doch noch eine weitere uci file wo ich das Zeug hinterlege oder?
Also User setzt uci get gateway.@client[$n].nat=1
Das set-revert-commit in 33-snat.conf liest das nun und muss nun irgendwohin ein uci set (und commit mit apply()) machen das dann von /usr/lib/firewall.d/30-NAT wieder gelesen werden kann. Wohin ist dieses irgendwohin?
Ich glaub das purzelt bei deiner Idee dann am Ende recht leicht mit raus, auch wenn wir gar keinen Mechanismus für [$n] aktuell haben (man kann es auch ohne NAT aktuell nicht verwenden) schau ich mal ob man das mit rein bekommt.
Ich hab zu @rohammer Idee hier mal ein RFC gemacht: #79
Kann zugemacht werden, geht hier weiter:
#79
Pull request closed