[Frage] Paket iptables: Wie werden Regeln mittels Script eingelesen

cmonty14

Mitglied
Mitglied seit
22 Jan 2007
Beiträge
378
Punkte für Reaktionen
0
Punkte
16
Hallo!
Ich habe (erfolgreich) ein Freetz-Image für die FB7170 gebaut u.a. mit den Paketen iptables und iptables-cgi.

Für Regeln, die über das Webinterface angelegt werden, gilt:
"[...] werden fest in den Flash-Speicher der Box gespeichert und gehen also nicht verloren."

Ich möchte die FB7170 als Router betreiben, wobei die Netzwerke voneinander getrennt sind. Im Freetz-Wiki findet man diesen Artikel.

Frage:
Wie können Bash-Scripte eingebaut werden, die man im Netz findet, wenn man nach "Firewall + DMZ + iptables" googelt?

Denn es wäre ziemlich mühsam, zig Regeln über das Webinterface zu pflegen, über die sich schon andere Leute Gedanken gemacht haben.

THX
 
Denn es wäre ziemlich mühsam, zig Regeln über das Webinterface zu pflegen, ...
Hier stimme ich dir zu. Ein Script ist besser als die Eingabe über das Webinterface.
... über die sich schon andere Leute Gedanken gemacht haben.
Hier stimme ich dir nicht zu. Man sollte kein iptables-Script von anderen Leuten übernehmen. Schreibe dein eigenes iptables-Script (... für deine Box bzw. für deine Konstellation).
 
Sicherheit ins Netzwerk zu bekommen ist immer mühsam. Daher erstelle Dir selbst ein Regelwerk, dass explizit Deine Belange befriedigt. Nur so kannst Du sicherstellen, dass Dein Router genau das macht was er soll. Solche mitunter kritischen Sachen kannst Du niemand anderes überlassen.

Wenn Du hingegen nur irgendwelche Regeln übernimmst, wo Du nichtmal weisst was diese Regeln tun, dann reisst Du Dir ziemlich schnell ein riesen Tor in Dein Netzwerk.
 
Wie können Bash-Scripte eingebaut werden, die man im Netz findet, wenn man nach "Firewall + DMZ + iptables" googelt?
Shell-Skripte werden einfach in der Shell ausgeführt. In diesem Fall enthalten die Skripte hauptsächlich Aufrufe des Programms iptables, das die Regeln im Kernel setzt.

Sicherheit ins Netzwerk zu bekommen ist immer mühsam. Daher erstelle Dir selbst ein Regelwerk, dass explizit Deine Belange befriedigt. Nur so kannst Du sicherstellen, dass Dein Router genau das macht was er soll.
Es stimmt, dass man besser wissen sollte, was man da tut. Das heißt aber nicht, dass jeder das Rad neu erfinden muss. Man sollte aber in der Lage sein, die Eignung der vorhandenen Skripte bzw. der davon erstellten Reglen für die eigene Situation abzuschätzen und diese ggf. anpassen können.
 
Hallo
Du kannst sowas super mit jeder greifbaren rc.xxx tricksen.
(rc.custom ist eine Adresse dafür)
Mit etwas Erfahrung, kannst du auch die .profile mit Shellskript-Funktionen austatten.
Sowas hat dann den Vorteil, dass sie sich überall und in jedes Skript einbinden lassen. (mit einem einfachen: . /mod/root/.profile)
Demzufolge sie sich auch von jeder beliebigen Stelle ausführen lassen können.

Beispiel für die rc.custom (Hier wird /var/led gepatcht, was AVM nie hinbekommen hat):
PHP:
#! /bin/sh
# PATCH /var/led --> /dev/led --> /dev/new_led
/bin/ln -sf /dev/new_led /dev/led
/bin/ln -sf /dev/led /var/led
/bin/update_led_on
# END OF PATCH

# LED cleanup (all off)
echo "SET error,0 =0" > /var/led
echo "SET power,0 =0" > /var/led
echo "SET power,1 =0" > /var/led
/bin/update_led_off
return 0
In deinem Fall würden halt die iptable Anweisungen drinnestehn.
Bedenke: Erst testen ohne automatischen Start! (iptables.cgi, ohne rc.custom) (Sonst sperrst du dich eventuell aus und musst recovern)

Noch ein Tip:
Den Editor von iptables.cgi finde ich unsäglich langsam, besonders wenn man schon 10 Regeln drinstehn hat.
Deswegen füge ich gerne neue Regeln direkt in /cgi-bin/file/iptables/rules ein (Copy'n'Paste).
So kannste natürlich auch "fremde" Regeln einfügen, zum testen oder wie auch immer.
Meistens reicht es ja, das voranstehende iptable zu löschen, nach dem Einfügen.
 
Zuletzt bearbeitet:
Hallo
[...]
Mit etwas Erfahrung, kannst du auch die .profile mit Shellskript-Funktionen austatten.
Sowas hat dann den Vorteil, dass sie sich überall und in jedes Skript einbinden lassen. (mit einem einfachen: . /mod/root/.profile)
Demzufolge sie sich auch von jeder beliebigen Stelle ausführen lassen können.
[...]

Könntest du bitte diese Funktion mit .profile näher erläutern, d.h. wie wird dies praktisch umgesetzt?

THX
 
Gerne
Also, lassen wir iptables dafür aber noch beiseite, den meine "working Examples" in der .profile habe nur mit den fünf LEDs der Fritz!Box zu tun.

Zuerst mal meine .profile:
(Achtung: usleep wird benutzt, kein Standardbefehl, muss busybox draufhaben (make menuconfig dann bei busybox in den coreutils, oder statische busybox mit usleep))
usleep kann aber durch sleep ersetzt werden, doch müssem dann alle ###second/s auf 1 gesetzt werden!
PHP:
#! /bin/sh
# die fritzbox LED's:
if [ $# -gt 0 ]
then
# Argument wurde uebergeben

# usleep konfigurieren
ksleep=/bin/usleep
octasecond=125000
quartersecond=250000
halfsecond=500000
second=1000000
fiveseconds=5000000

# Das Lauflicht vorbereiten...
leftright () { #von links nach rechts
 echo "SET power,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET power,0 = 0" > /dev/new_led
 echo "SET internet,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET internet,0 = 0" > /dev/new_led
 echo "SET ab,1 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET ab,1 = 0" > /dev/new_led
 echo "SET wlan,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET wlan,0 = 0" > /dev/new_led
 echo "SET info,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET info,0 = 0" > /dev/new_led
}

rightleft () { #von rechts nach links
 echo "SET info,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET info,0 = 0" > /dev/new_led
 echo "SET wlan,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET wlan,0 = 0" > /dev/new_led
 echo "SET ab,1 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET ab,1 = 0" > /dev/new_led
 echo "SET internet,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET internet,0 = 0" > /dev/new_led
 echo "SET power,0 = 1" > /dev/new_led
 $ksleep $octasecond
 echo "SET power,0 = 0" > /dev/new_led
}

all_off () {
# Alle aus (auch der zus. power u. internet Slot):
 echo "SET power,0 = 0" > /dev/new_led
 echo "SET power,1 = 0" > /dev/new_led
 echo "SET internet,0 = 0" > /dev/new_led
 echo "SET internet,1 = 0" > /dev/new_led
 echo "SET ab,1 = 0" > /dev/new_led
 echo "SET ab,2 = 0" > /dev/new_led
 echo "SET ab,3 = 0" > /dev/new_led
 echo "SET wlan,0 = 0" > /dev/new_led
 echo "SET info,0 = 0" > /dev/new_led
}

all_on () {
# Alle an:
 echo "SET power,0 = 1" > /dev/new_led
 echo "SET internet,0 = 1" > /dev/new_led
 echo "SET ab,1 = 1" > /dev/new_led
 echo "SET wlan,0 = 1" > /dev/new_led
 echo "SET info,0 = 1" > /dev/new_led
}

all_slow () {
# Alle blinken langsamer:
 echo "SET power,0 = 16" > /dev/new_led
 echo "SET internet,0 = 16" > /dev/new_led
 echo "SET ab,1 = 16" > /dev/new_led
 echo "SET wlan,0 = 16" > /dev/new_led
 echo "SET info,0 = 16" > /dev/new_led
}

all_med () {
# Alle blinken langsam:
 echo "SET power,0 = 17" > /dev/new_led
 echo "SET internet,0 = 17" > /dev/new_led
 echo "SET ab,1 = 17" > /dev/new_led
 echo "SET wlan,0 = 17" > /dev/new_led
 echo "SET info,0 = 17" > /dev/new_led
}

all_fast () {
# Alle blinken schnell:
 echo "SET power,0 = 18" > /dev/new_led
 echo "SET internet,0 = 18" > /dev/new_led
 echo "SET ab,1 = 18" > /dev/new_led
 echo "SET wlan,0 = 18" > /dev/new_led
 echo "SET info,0 = 18" > /dev/new_led
}

all_rapid () {
# Alle blinken ultraschnell:
 echo "SET power,0 = 19" > /dev/new_led
 echo "SET internet,0 = 19" > /dev/new_led
 echo "SET ab,1 = 19" > /dev/new_led
 echo "SET wlan,0 = 19" > /dev/new_led
 echo "SET info,0 = 19" > /dev/new_led
}

if [ $1 = "off" ]
then
# Alle aus:
 all_off
fi

if [ $1 = "on" ]
then
# Alle an:
 all_on
fi

if [ $1 = "slow" ]
then
# Alle blinken langsamer:
 all_slow
fi

if [ $1 = "med" ]
then
# Alle blinken langsam:
 all_med
fi

if [ $1 = "fast" ]
then
# Alle blinken schnell:
 all_fast
fi

if [ $1 = "rapid" ]
then
# Alle blinken ultraschnell:
 all_rapid
fi

if [ $1 = "run" ]
then
# Lauflicht:
 leftright
 $ksleep $octasecond
 rightleft
fi

if [ $1 = "test" ]
then
 all_off
 all_on
 $ksleep $second
 leftright
 $ksleep $quartersecond
 all_slow
 $ksleep $fiveseconds
 rightleft
 $ksleep $quartersecond
 all_med
 $ksleep $fiveseconds
 leftright
 $ksleep $quartersecond
 all_fast
 $ksleep $fiveseconds
 rightleft
 $ksleep $quartersecond
 all_rapid
 $ksleep $fiveseconds
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 leftright
 $ksleep $octasecond
 rightleft
 $ksleep $octasecond
 all_on
 $ksleep $halfsecond
 all_off
fi

if [ $1 = "help" ]
then
 echo "help:"
 echo " one of:"
 echo "off on slow med fast rapid run test"
fi

fi
#EO leds
# ALIASES
alias l='ls -AFXhlp --color'
# farbiges Prompt
export PS1="\[\033[0;32m\]\u\[\033[1;34m\]@\[\033[0;32m\]\h\[\033[1;35m\]:\[\033[1;33m\]\w\[\033[0m\]\[\033[1;34m\]#\[\033[0m\] "
return 0
Hier sind, wie du siehst, eine ganze Menge Funktionen drin, alle haben folgendes gemeinsam:
In der .profile werden die Funktionen definiert, aber nicht ausgeführt <--- <<< WICHTIG
Eine Funktionsdefinition hat folgenden Aufbau: Funktions_Name () {...}
...zwischen den geschweiften Klammern steht der ausführbare Code.
Eine Funktion wird mit ihrem Namen aufgerufen und verhält sich dann genauso wie ein Skript oder Programm.
Wenn im ausführbaren Code Parameter ausgewertet werden, können der Funktion auch auswertbare Parameter übergeben werden.
Beispiel: Funktions_Name Parameter1 Parameter2 usw
In der runden Klammer kann ein oder mehrere Parameter als Variablenname stehn, die dann im Code nicht extra definiert werden müssen, sie können auch default Werte vorhalten.
Beispiel: Funktions_Name (para1=$LOGNAME) {...}
Wenn para1 ($1) dann übergeben worden ist, enthält er den übergebenen Wert, wenn nicht dann $LOGNAME.

So, das war die Theorie, weiter mit meiner .profile....
Die ist nämlich so geskriptet, dass sie Parameter auswertet, soll heissen, ich ruf .profile gefolgt von einem Textstring, das Skript wertet das dann aus und führt an richtiger Stelle den Code aus.
(nur dann, wenn ein Parameter übergeben wird, werden die Funktionen auch definiert, ist ein plumper Trick)
Bei mir findet sowas zB. in meiner crontab statt:
crontab
PHP:
* * * * * /bin/sh $HOME/.profile run
("run" Jede Minute wird ein Lauflicht von Links nach Rechts und wieder zurück auf meinen Fritz!Box LEDs flitzen, danach ist wieder 59 Sekunden Ruhe)

Logik im Skript:
1. Parameter bekommen.
2. Funktionsdefinitionen.
3. Parameterauswertung.
4. Parameter "run" bekannt, verzweige und führe weitergehenden Anweisungen aus.
5. Anweisungen mit Funktionsaufrufen werden ausgeführt.
6. Skript beendet sich.

Funktionen werden meistens für sich wiederholende Abläufe benötigt.
(Glaubst du nicht? Dann schau dir mal an was bei .profile test ausgeführt wird :) )

Im Prinzip sind definierte Funktionen als "Skript im Skript" zu sehen, lassen sich inkludieren (in einem Skript nachladen) oder werden eben im aktuellen Skript am Anfang definiert, damit man sie am Ende (nach ihrer Definition) schon benutzen kann.
Ich hab schon Definitionen von Funktionen als Umgebungsvariablen gesehn und selbst ein alias lässt sich so frisieren :)
 
Zuletzt bearbeitet:
Wie können Bash-Scripte eingebaut werden

Wieso steckst Du nicht einfach einen USB-Stick an die Box und legst ein Script unter /var/media/ftp/uStor*/... ab, das mit Deinen (ggfs. vom Wiki-Beispiel ausgehenden) Regeln befüllt wird ? Dieses kannst Du in der rc.costum beim Starten ausführen lassen.
Das Iptables-CGI nutze ich auch nur zum schnellen Draufgucken und/oder um ggfs. schnell die eine oder andere Regel löschen zu können.
Grüße,

JD.
 
Moin
Vielleicht wollte c.monty nur wissen wie Funktionen funktionieren?
Es ist auf jedenfall nicht verkehrt, sehn wirs einfach als Bereicherung.

Mir ist auch aufgefallen, dass bestimmte, aber elaubte Ausdrücke, nicht über den iptables.cgi Editor eingegeben werden können.
Über die direkte Eingabe bei den Regeln aber schon, Beispiel: -A INPUT -p tcp -m tcp ! --dport 81 -j LOG --log-prefix "[IPT] TCP INPUT "
Zu beachten: Die Inversion mittels dem Ausrufezeichen (!) und zusätzlicher Parameter --log-prefix.
Bei den Regeln wirds nach klick auf "Übernehmen" im Editor aber trotzdem richtig Angezeigt.

In diesem Zusammenhang wäre es doch ganz nett, wenn man die "iptables.cgi - rules" austauschen könnte.
Per Skript oder Funktion, wäre ja egal.
Also im Sinne von:
/etc/init.d/rc.iptables stop
cp rules rules.old
cp rules.new rules
/etc/init.d/rc.iptables start
 
Zuletzt bearbeitet:
Es loggt einfach alles (TCP) was nicht freetz-WebIf ist, ich guck mir sowas an um zu sehen was sonst nocht so beim TCP-Verkehr verkehrt.

Zum Beispiel:
Code:
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=126 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0 
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=127 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0 
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=128 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0 
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=131 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0 
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=132 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0 
[IPT] TCP INPUT IN=lan OUT= MAC=00:xx:4a:xx:39:xx:00:1c:4a:42:ff:xx:08:00 SRC=85.183.xxx.xxx DST=10.1.1.1 LEN=42 TOS=0x00 PREC=0x00 TTL=124 ID=135 DF PROTO=TCP SPT=1034 DPT=23 WINDOW=63905 RES=0x00 ACK PSH URGP=0

Ausserdem, kann ein zufälliger Mitleser dieses Beispiel ohne die Gefahr eines sich selber aussperrens, sofort ausprobieren und nachvollziehen.
Und erst dannach kommt die entsprechende Regel zum "Fallenlassen":
-A INPUT -p tcp -m tcp ! --dport 81 -j DROP
Also: Erst loggen und gucken was los ist und passiert und dann erst dichtmachen.
(Was dazu führen würde, dass unter anderem, telnet Pakete sofort fallengelassen werden)
So fahr ich eigentlich ganz gut und kann Schritt für Schritt loggen lassen bevor ich dann letztendlich die DROP-Regel setze.

Wenn dass nicht richtig ist, klär mich bitte auf, denn solange mach ich mit iptables auch noch nicht rum.
 
Zuletzt bearbeitet:
Nach meinem Verständnis dient die Mangle Table (teilweise) zum Verändern von Paketen, u.A. der Paket-Header (SNAT, DNAT usw.).
Demzufolge glaube ich, dass der Teil -m tcp ! --dport ins Leere läuft. Insbesondere halte ich auch sicherheitstechnischen Gründen Regeln, die in gewisser Form whitelist-basiert sind, für besser, also nur bekannte Quellen/Ports dürfen rein/durch, der Rest nicht. Das, was Du mit Deiner Regel erzielen willst, klappt mit
Code:
iptables -A INPUT -p tcp --dport 81 -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "[IPT] TCP INPUT"
iptables -A INPUT -p tcp -j DROP
in jedem Fall.
Grüße,

JD.
 
Ja, dankeschön, dass nehm ich mir mal an, probiers aus, betonier es ein ;)
Geschrieben, getan, fertig!

Und du hast Recht, auf diese Weise erstellte Regeln bieten mehr Übersicht über die erlaubten Ports, quasi mit einem Blick ;)

rules
Code:
*nat
:PREROUTING ACCEPT [6:264]
:POSTROUTING ACCEPT [2:117]
:OUTPUT ACCEPT [2:117]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [90:23562]
-A INPUT -p tcp --dport 81 -j ACCEPT
-A INPUT -p tcp --dport 23 -j ACCEPT
-A INPUT -j LOG --log-prefix "[IPT] INPUT"
-A INPUT -p tcp -j DROP
-A INPUT -p udp -j DROP
-A INPUT -p icmp -j DROP
COMMIT

Wie loggt man eigentlich nur die Pakete die verworfen (DROP) worden sind?

Dazu hab ich folgendes gefunden:
Code:
iptables -N DROPCHAIN
iptables -A DROPCHAIN -j LOG -m limit --limit 5/s --log-prefix "INPUT-DROP:"
iptables -A DROPCHAIN -j DROP
Das geht allerdings nicht über die iptables.cgi Regeln, weil eben eine neue Kette erzeugt wird, was anscheinend nicht vorgesehen ist.
EDIT: Geht doch:
Code:
# Generated by iptables-save v1.4.11.1 on Mon Apr 22 11:09:14 2013
*nat
:PREROUTING ACCEPT [2:88]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Mon Apr 22 11:09:14 2013
# Generated by iptables-save v1.4.11.1 on Mon Apr 22 11:09:14 2013
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [118:26713]
:DROPCHAIN - [0:0]
-A INPUT -p tcp -m tcp --dport 81 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 23 -j ACCEPT
-A INPUT -p tcp -j DROP
-A INPUT -p udp -j DROP
-A INPUT -p icmp -j DROP
-A DROPCHAIN -j LOG --log-prefix "[IPT][DROP]: "
COMMIT
# Completed on Mon Apr 22 11:09:14 2013
Aber es gibt noch Probleme mit: -m limit --limit 5/s
Fehlermeldung: iptables: No chain/target/match by that name.
 
Zuletzt bearbeitet:
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.