Hallo,
ich habe mir hier folgende kleine Aufgabe für mich: Ich möchte meine DHCP-Server im Netz betreiben und moechte nur Clients mit einer bestimmten MAC zulassen. Dazu hab' ich ein kleines iptables script das erst mal alle Anfragen via udp an port 67(bootps) blockiert. Doch das will nicht, zumindest nicht auf der Debian Kiste. Auf der susi laeuft das einwandfrei, auf dem Debian greifen die Regeln nicht.
Konfig SuSE:
Kernel 2.6.8-24.18-default / iptables 1.2.11
Konfig Debian:
Kernel 2.6.16-1-686 / iptables 1.3.3
Code:
Chain INPUT (policy ACCEPT 15090 packets, 10M bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT udp -- any any anywhere anywhere udp dpt:bootps reject-with icmp-port-unreachable
0 0 REJECT tcp -- any any anywhere anywhere tcp dpt:bootps reject-with icmp-port-unreachable
7 460 ACCEPT all -- any any anywhere anywhere
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 289K packets, 447M bytes)
pkts bytes target prot opt in out source destination
Irgendeine Idee woran das liegen koennte?
-----
Hintergrund:
Ich betreibe einen 2. DHCP-Server als Netzbootserver, der bei Bedarf Rettungs(Knoppix) und Installationssystem(FAI) bereitstellen soll. Über eine Web-oberflaeche sollen dann Nutzer MAC-Adressen eingeben sollen, die dann adhoc via iptables freigeschaltet werden.
Hier das cgi:
Code:
#!/usr/bin/perl
use CGI qw/:fatals_to_browser :standard :form *table/;
use strict;
use constant MAC_FILE => '/etc/dhcp3/mac-access/macs.txt';
print header;
print start_html('DHCP-Zugriffssteuerung fuer den Netzbootserver');
print start_form();
my $cgi=CGI->new();
my $self=$cgi->url();
my $error;
my $message;
my $action=0;
print "<h1>DHCP-Zugriffssteuerung fuer den Netzbootserver</h1>\n";
if (param()) {
if(param("mac")) {
my $mac=param("mac");
chomp($mac);
&convertmac(\$mac) or &error("$mac ist keine gueltige MAC-Adresse");
unless($error) {
if(&macneu($mac)) {
&info("MAC Adresse $mac hinzugefuegt");
&writemac($mac);
$action=1;
} else {
&error("MAC Adresse schon vorhanden");
}
}
}
if(param("DELETE_MAC")) {
my $mac=param("DELETE_MAC");
chomp($mac);
if(&macneu($mac)) {
&error("MAC: $mac existiert nicht in der Datei");
} else {
if(&deletemac($mac) ) {
&info("MAC: $mac wurde geloescht");
$action=1;
}
}
}
&showmacs();
&printmessage();
if($action) {
system("/usr/bin/sudo /usr/local/bin/fw-dhcp-blocker");
&info("Systemkonfiguration wurde geandert");
&printmessage();
}
} else {
&showmacs()
}
print end_form();
print end_html();
exit(0);
sub showmacs {
# MAC-Adressen aus Datei lesen
my @MACS=&getmacs();
$cgi->delete_all();
# MAC-Adressen anzeigen
print "<P>Neue MAC-Adresse: ".$cgi->textfield(-name=>"mac",-size=>40,).$cgi->submit(-value=>"Hinzufuegen")."</P>\n";
print "<font size=4><b>Freigeschaltete MAC-Adressen</b></font>";
print "<TABLE>\n";
for my $ADDR (@MACS) {
print "<TR><TD>$ADDR</TD><TD><A HREF=\"$self?DELETE_MAC=$ADDR\">loeschen</A></TD></TR>\n";
}
print "</TABLE>\n";
}
sub getmacs {
open(MACS,"<".MAC_FILE) or &error("Kann macs.txt nicht lesen: $!");
my @list;
while(<MACS>) {
chomp();
push(@list,$_);
}
close(MACS);
return(@list);
}
sub writemac {
my $mac=shift;
open(MACS,">>".MAC_FILE) or &error("Kann macs.txt nicht zum schreiben oeffnen: $!");
print MACS "$mac\n";
close(MACS);
}
sub writemacs {
my $macs=shift;
open(MACS,">".MAC_FILE) or &error("Kann macs.txt nicht zum schreiben oeffnen: $!");
for my $ADDR (@$macs) {
print MACS "$ADDR\n";
}
close(MACS);
}
sub macneu {
my $newmac=shift;
my @MACS=&getmacs();
for my $ADDR (@MACS) {
return(0) if($ADDR eq $newmac);
}
return(1);
}
sub deletemac {
my $mac=shift;
my @MACS=&getmacs();
my @NEWMACS;
my $ADDR;
for $ADDR ( @MACS ) {
if($ADDR ne $mac) {
push(@NEWMACS,$ADDR);
}
}
&writemacs(\@NEWMACS);
}
sub convertmac {
my $mac=shift;
if( $$mac =~ /^([0-9a-fA-F]{2}[:-]?){5}[0-9a-fA-F]{2}$/ ) {
$$mac =~ s/-/:/g;
$$mac =~ s/([a-f])/\U$1/g;
return(1);
}
return(0);
}
sub printmessage {
print "<p> </p>";
print $message;
}
#sub writemac {
sub error {
my $msg=shift;
$message="<font size=5 color=red>Fehler: $msg</font>\n";
$error=1;
# die($msg);
}
sub info {
my $msg=shift;
$message="<font size=5 color=green>$msg</font>\n";
$error=0;
# die($msg);
}
sub debug {
my $msg=shift;
print "<font size=5 color=orange>$msg</font>\n";
# die($msg);
}
#!/usr/bin/perl
use CGI qw/:fatals_to_browser :standard :form *table/;
use strict;
use constant MAC_FILE => '/etc/dhcp3/mac-access/macs.txt';
print header;
print start_html('DHCP-Zugriffssteuerung fuer den Netzbootserver');
print start_form();
my $cgi=CGI->new();
my $self=$cgi->url();
my $error;
my $message;
my $action=0;
print "<h1>DHCP-Zugriffssteuerung fuer den Netzbootserver</h1>\n";
if (param()) {
if(param("mac")) {
my $mac=param("mac");
chomp($mac);
&convertmac(\$mac) or &error("$mac ist keine gueltige MAC-Adresse");
unless($error) {
if(&macneu($mac)) {
&info("MAC Adresse $mac hinzugefuegt");
&writemac($mac);
$action=1;
} else {
&error("MAC Adresse schon vorhanden");
}
}
}
if(param("DELETE_MAC")) {
my $mac=param("DELETE_MAC");
chomp($mac);
if(&macneu($mac)) {
&error("MAC: $mac existiert nicht in der Datei");
} else {
if(&deletemac($mac) ) {
&info("MAC: $mac wurde geloescht");
$action=1;
}
}
}
&showmacs();
&printmessage();
if($action) {
system("/usr/bin/sudo /usr/local/bin/fw-dhcp-blocker");
&info("Systemkonfiguration wurde geandert");
&printmessage();
}
} else {
&showmacs()
}
print end_form();
print end_html();
exit(0);
sub showmacs {
# MAC-Adressen aus Datei lesen
my @MACS=&getmacs();
$cgi->delete_all();
# MAC-Adressen anzeigen
print "<P>Neue MAC-Adresse: ".$cgi->textfield(-name=>"mac",-size=>40,).$cgi->submit(-value=>"Hinzufuegen")."</P>\n";
print "<font size=4><b>Freigeschaltete MAC-Adressen</b></font>";
print "<TABLE>\n";
for my $ADDR (@MACS) {
print "<TR><TD>$ADDR</TD><TD><A HREF=\"$self?DELETE_MAC=$ADDR\">loeschen</A></TD></TR>\n";
}
print "</TABLE>\n";
}
sub getmacs {
open(MACS,"<".MAC_FILE) or &error("Kann macs.txt nicht lesen: $!");
my @list;
while(<MACS>) {
chomp();
push(@list,$_);
}
close(MACS);
return(@list);
}
sub writemac {
my $mac=shift;
open(MACS,">>".MAC_FILE) or &error("Kann macs.txt nicht zum schreiben oeffnen: $!");
print MACS "$mac\n";
close(MACS);
}
sub writemacs {
my $macs=shift;
open(MACS,">".MAC_FILE) or &error("Kann macs.txt nicht zum schreiben oeffnen: $!");
for my $ADDR (@$macs) {
print MACS "$ADDR\n";
}
close(MACS);
}
sub macneu {
my $newmac=shift;
my @MACS=&getmacs();
for my $ADDR (@MACS) {
return(0) if($ADDR eq $newmac);
}
return(1);
}
sub deletemac {
my $mac=shift;
my @MACS=&getmacs();
my @NEWMACS;
my $ADDR;
for $ADDR ( @MACS ) {
if($ADDR ne $mac) {
push(@NEWMACS,$ADDR);
}
}
&writemacs(\@NEWMACS);
}
sub convertmac {
my $mac=shift;
if( $$mac =~ /^([0-9a-fA-F]{2}[:-]?){5}[0-9a-fA-F]{2}$/ ) {
$$mac =~ s/-/:/g;
$$mac =~ s/([a-f])/\U$1/g;
return(1);
}
return(0);
}
sub printmessage {
print "<p> </p>";
print $message;
}
#sub writemac {
sub error {
my $msg=shift;
$message="<font size=5 color=red>Fehler: $msg</font>\n";
$error=1;
# die($msg);
}
sub info {
my $msg=shift;
$message="<font size=5 color=green>$msg</font>\n";
$error=0;
# die($msg);
}
sub debug {
my $msg=shift;
print "<font size=5 color=orange>$msg</font>\n";
# die($msg);
}
Hier das zugehoerige iptables-script:
Code:
#!/bin/bash
ipt=/sbin/iptables
$ipt -Z
$ipt -X
$ipt -F INPUT
$ipt -F
$ipt -A INPUT -p udp --dport 67 -j REJECT
$ipt -A INPUT -p tcp --dport 67 -j REJECT
for mac in $(cat /etc/dhcp3/mac-access/macs.txt)
do
$ipt -I INPUT -p tcp -m mac,tcp --mac-source $mac --dport 67 -j ACCEPT
$ipt -I INPUT -p udp -m mac,udp --mac-source $mac --dport 67 -j ACCEPT
done
$ipt -A INPUT -j ACCEPT
Lesezeichen