ubuntuusers.de

nathelper

Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:

Dieser Artikel ist größtenteils für alle Ubuntu-Versionen gültig.

Artikel für fortgeschrittene Anwender

Dieser Artikel erfordert mehr Erfahrung im Umgang mit Linux und ist daher nur für fortgeschrittene Benutzer gedacht.

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

Dieses Perl-Skript dient dazu, mit einem einzigen Kommandozeilenbefehl einen Ubuntu-Router mit der nötigen Network Address Translation (NAT) Funktionalität auszustatten, ohne dass man sich mit der iptables-Syntax beschäftigen muss.

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 einem Startskript (bspw. in /etc/rc.local) konservieren.

Syntax

Das Skript wird komplett über seine Argumente gesteuert[1]:

nathelper -i IFACE OPTIONEN IP PORT(S) 

Beispiele:

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:

nathelper -i ppp+ -m 192.168.1.1 21-25,80,3128:10001-10007 

Achtung!

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.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/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 <<EOT;
Usage: $0 [-v] [-d] -i iface [-m] [ip ports ...] ...
       $0 [-h]

-h : Hilfe
-v : Verbose, iptables-Befehle ausgeben und durchfuehren
-d : Debug, nicht wirklich durchfuehren
-q : Keine Erfolgsmeldung ausgeben
-i : externes Interface
-m : Masquerading aktivieren

ip ports : Ports, die auf IP umgeleitet werden, mehrere moeglich
ports : 1234 -> 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);
}

Diese Revision wurde am 14. Januar 2012 16:30 von frustschieber erstellt.
Die folgenden Schlagworte wurden dem Artikel zugewiesen: Shell, Netzwerk