[[Vorlage(getestet, jammy, focal, bionic)]] [[Vorlage(Fortgeschritten)]] {{{#!vorlage Wissen [:Terminal: Ein Terminal öffnen] }}} Dieses [:Perl:]-Skript dient dazu, mit einem einzigen Kommandozeilenbefehl einen Ubuntu-Router mit der nötigen Network Address Translation (NAT) Funktionalität für IPv4 auszustatten, ohne dass man sich mit der [:iptables: iptables-Syntax] beschäftigen muss. IPv6 wird im Skript nicht berücksichtigt. = Installation und Benutzung = Einfach das Skript irgendwo hin kopieren, wo es passt, bspw. nach '''/usr/local/sbin/nathelper'''. Dann die geeigneten Kommandozeilenargumente (s.u.) zusammenstellen und wenn alles wie gewünscht funktioniert den Befehl in einer [:systemd/Units:Systemd-Unit] konservieren. {{{#!vorlage Hinweis Beim Testen muss man dieses Skript natürlich als [:root:] bzw. mit [:sudo:] aufrufen, weil es selbst [:iptables:] benutzt. Dieses Perl-Skript läuft natürlich nicht unter anderen Programmiersprachen, die z.B. wie "Perl 6" alias Raku zwar das Wort "Perl" im Namen führen, aber nicht Perl sind. Nur "Perl 5" ist echtes Perl und standardmäßig bei Ubuntu installiert. }}} = Syntax = Das Skript wird komplett über seine Argumente gesteuert[1]: {{{#!vorlage Befehl nathelper -i IFACE OPTIONEN IP PORT(S) }}} Beispiele: {{{#!vorlage Befehl nathelper -i ppp+ -m # nur Masquerading nathelper -i ppp+ -m 192.168.6.5 80 21 192.168.6.6 6881-6889:7001-7009 # Masquerading und verschiedene Port-Weiterleitungen }}} In diesem Beispiel wird auf dem externen ppp-Device (`ppp+` ist ein Joker-Ausdruck, der auf alle ppp-Devices zutrifft) Masquerading eingerichtet, sowie ein paar Ports nach innen weitergeleitet. Die Ports 80 und 21 werden an den Rechner 192.168.6.5 weitergeleitet und die Ports 6881 bis 6889 werden an die Ports 7001 bis 7009 des Rechners 192.168.6.6 weitergeleitet. == Optionen == * `-i iface`: Gibt die externe Netzwerkschnittstelle an. Für (DSL-)Modems sollte man einfach `ppp+` verwenden, ansonsten bspw. `eth0`. Diese Option muss unbedingt angegeben werden. * `-m`: Diese Option gibt an, dass Masquerading verwendet werden soll. Dies ist in den allermeisten Fällen der Fall. * `-v`: Gibt jeden '''sysctl'''- und '''iptables'''-Befehl auf der Konsole aus, bevor er ausgeführt wird. So kann man nebenbei die '''iptables'''-Syntax lernen oder die Funktionsweise des Skriptes kontrollieren. * `-d`: Wie `-v`, allerdings werden die Befehle nur ausgegeben, aber nicht tatsächlich ausgeführt. * `-q`: Am Ende des Skripts wird normalerweise eine Erfolgsmeldung ausgegeben. Mit Angabe der Option `-q` unterbleibt dies. * `ip`: Wird ohne benannte Option auf der Kommandozeile angegeben. Bezeichnet die IP-Adresse eines Rechners, an den Port(s) weitergeleitet werden. Alle nachfolgenden ''port''-Argumente bis zur nächsten IP beziehen sich auf diese Adresse. * `ports`: Ein Weiterleitungsstatement, dass sich immer auf die letzte vorhergehende IP-Adressenbezeichnung bezieht. Folgende Möglichkeiten gibt es: * `1234` -> Der Port 1234 wird 1:1 an denselben Port des Zielrechners weitergeleitet. * `1234-1238` -> Ein ganzer Abschnitt von Ports wird weitergeleitet. * `1234,1370` -> Mehrere verschiedene Ports werden weitergeleitet. * `1234:5678` -> Ein Port wird auf einen anderen Port des Zielrechners weitergeleitet. * `u1234` -> Dieses Port-Statement bezieht sich auf das UDP-Protokoll an Stelle des meist verwendeten TCP-Protokolls. Die verschiedenen Operatoren können auch alle miteinander kombiniert werden, wobei aber auf eine gleiche Anzahl Ports rechts und links vom `:` geachtet werden muss. Beispiel: {{{#!vorlage Befehl nathelper -i ppp+ -m 192.168.1.1 21-25,80,3128:10001-10007 }}} {{{#!vorlage Warnung Für jeden einzelnen Port wird eine [:iptables:]-Regel angelegt, was sich bei einer sehr hohen Anzahl an Regeln durchaus auf die Performance auswirken kann. Es ist deswegen nicht empfehlenswert, aus Bequemlichkeit bspw. mit `1-65535` alle Ports umzuleiten. }}} * [attachment:Skripte/nathelper/nathelper:Hier das Skript herunterladen.] {dl} {{{#!code perl #!/usr/bin/perl -w # # nathelper - Masquerading und Port-Forwarding in einer Kommandozeile # benoetigt natuerlich iptables # # Autor: otzenpunk (UbuntuUsers.de) # Lizenz: Public Domain use strict; use Getopt::Std; our %opts; usage() unless @ARGV; getopts('qvdhmi:', \%opts); usage() if $opts{'h'} or !$opts{'i'}; init(); # ip_forward, iptables -F masq($opts{'i'}) if ($opts{'m'}); # evtl. Masquerading our @forwards; our $fw_indx = 0; while ($_ = shift @ARGV) { # Array of Arrays: je 1xIP und n x Ports ++$fw_indx if /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && @forwards; push @{$forwards[$fw_indx]}, $_; } forw($_) for @forwards; # jede IP verarbeiten print "NAT erfolgreich aktiviert.\n" unless $opts{'q'} or $opts{'d'}; exit(0); # masq(iface): Masquerading sub masq { my @iptables = (qw(/sbin/iptables -t nat -A POSTROUTING -o), $opts{'i'}, qw(-j MASQUERADE)); iptables(@iptables); } # forw(IP, Ports, ...): Ports duerfen Aufzaehlungen (zahl,zahl) # Ranges (zahl-zahl) # und Uebersetzungen (zahl:zahl) enthalten. sub forw { my $argptr = shift; # Pointer auf Array my $ip = shift @$argptr; # Erstes Element = IP for (@$argptr) { s/[^0-9u:,-]//ig; # saeubern von verbotenen Zeichen my $proto = s/^u//i ? 'udp' : 'tcp'; # u = UDP my ($von, $nach) = split ':'; # Uebersetzung trennen $nach ||= $von; # wenn kein ':' -> Ports bleiben gleich my @von = expand_range($von); # ',' und '-' expandieren my @nach = expand_range($nach); unless (@von == @nach) { # Falsche Parameter abfangen: print "Ungleiche Anzahl Ports: ", join(', ', @von), ' -> ', join(', ', @nach), "\n\n"; usage(); } my $i = 0; for (@von) { # je eine iptables-Zeile pro Port my @iptables = (qw(/sbin/iptables -t nat -A PREROUTING -i), $opts{'i'}, '-p', $proto, '--dport', $_, qw(-j DNAT --to-destination), "$ip:$nach[$i++]"); iptables(@iptables); } } } # iptables(Liste der Argumente, inkl. iptables-Pfad) sub iptables { # system() gibt >0 bei Fehler print join(' ', @_), "\n" if $opts{'v'} or $opts{'d'}; system(@_) && die("Fehler bei iptables. Root?\n") unless ($opts{'d'}); } # expand_range(Port-String inkl. [,-]) # ',' und '-' expandieren und Liste zurueck sub expand_range { my @werte = split ',', shift; @werte = map { my ($down, $up) = split '-', $_; $down < ($up ||= 0) ? ($down..$up) : $down; } @werte; return @werte; } sub init { print "sysctl -w net/ipv4/ip_forward=1\n" if $opts{'v'} or $opts{'d'}; system(qw(sysctl -w net/ipv4/ip_forward=1)) if not $opts{'d'}; iptables(qw(/sbin/iptables -t nat -F)); } sub usage { print < Port wird 1:1 umgeleitet 1234:5678 -> Port wird auf anderen Port umgeleitet 1234-1238 -> Port-Range wird umgeleitet 1234-1238:5674-5678 -> beides u1234 -> UDP-Port(s) verwenden EOT exit(1); } }}} # tag: Shell, Netzwerk, System