From: root Date: Sat, 7 Apr 2007 16:30:09 +0000 (+0200) Subject: Merge. X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=cc0b9f43fe25834abfa41bb3bf57306865a608f8;hp=de1b28e7de97f6f969c1c02e5b8d22f1eaedbbf9;p=nms Merge. --- diff --git a/.bzrignore b/.bzrignore index 5f71d77..77ff49d 100644 --- a/.bzrignore +++ b/.bzrignore @@ -4,3 +4,6 @@ patchlist.txt switches.txt planning/planning mbd/nets.pl +switches.sql +include/config.local.pm +mbd/mbd.log diff --git a/clients/dhcpv6gen.pl b/clients/dhcpv6gen.pl new file mode 100644 index 0000000..83db735 --- /dev/null +++ b/clients/dhcpv6gen.pl @@ -0,0 +1,30 @@ +open PATCHLIST, "/root/nms/switches.txt" + or die "switches.txt: $!"; +my %vlans = (); + +while () { + if (/87\.76\.(\d+)\.(\d+) 26 e(\d+)-(\d+)/) { + my $vlannum = $3.$4; + my $helper = "87.76.$1." . ($2+1); + my $name = "e$3-$4"; + my $z = sprintf "f%03u", $vlannum; + $z =~ /(.)(.)(.)(.)/; $vlans{$helper} = [ $vlannum, $name, "$4.$3.$2.$1" ]; + } +} + +while (<>) { + /DHCPOFFER on 87.76.\d+.\d+ to 00:(.)(.):(.)(.):(.)(.):(.)(.):(.)(.) \((.*?)\) via (\d+\.\d+\.\d+\.\d+)/ or next; + my $v = $vlans{$12}; + open NSUPDATE, "| nsupdate -y DHCP_UPDATER:F388UOhaIIKHRH9TDE5PTA=="; + print NSUPDATE <<"EOF"; +server 127.0.0.1 +update delete $11.v6.$v->[1].tg07.gathering.org. AAAA +update add $11.v6.$v->[1].tg07.gathering.org. 3600 AAAA 2001:16d8:ffff:f$v->[0]:02$1$2:$3$4ff:fe$5$6:$7$8$9$10 +send +update delete $10.$9.$8.$7.$6.$5.e.f.f.f.$4.$3.$2.$1.2.0.$v->[2].f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa. PTR +update add $10.$9.$8.$7.$6.$5.e.f.f.f.$4.$3.$2.$1.2.0.$v->[2].f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa. 3600 PTR $11.v6.$v->[1].tg07.gathering.org. +send +EOF + close NSUPDATE; +} + diff --git a/config/make-named-secondary.pl b/config/make-named-secondary.pl index a9b3c12..4f4047f 100755 --- a/config/make-named-secondary.pl +++ b/config/make-named-secondary.pl @@ -46,6 +46,23 @@ zone "tg07.gathering.org" { file "tg07.gathering.org"; }; +// hijack +zone "sth.ip-performance.se" { + type slave; + notify no; + masters { 87.76.254.2; }; + file "sth.ip-performance.se"; +}; + +// linknett +zone "0.76.87.in-addr.arpa" { + type slave; + notify no; + masters { 87.76.254.2; }; + file "0.76.87.in-addr.arpa"; + allow-transfer { 193.0.0.0/22; }; +}; + // linknett zone "174.76.87.in-addr.arpa" { type slave; @@ -88,6 +105,15 @@ zone "76.87.in-addr.arpa" { file "dynamic/76.87.in-addr.arpa"; allow-transfer { 194.19.3.20; 193.0.0.0/22; }; }; +zone "f.f.f.f.8.d.6.1.1.0.0.2.ip6.in-addr.arpa" { + type slave; + notify no; + masters { 87.76.254.2; }; + allow-update { key DHCP_UPDATER; }; + file "dynamic/f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa"; + allow-transfer { 194.19.3.20; }; +}; + key DHCP_UPDATER { algorithm HMAC-MD5.SIG-ALG.REG.INT; diff --git a/config/make-named.pl b/config/make-named.pl index d2bbf02..2fb295b 100755 --- a/config/make-named.pl +++ b/config/make-named.pl @@ -46,6 +46,22 @@ zone "tg07.gathering.org" { allow-transfer { 87.76.255.2; }; }; +// hijack +zone "sth.ip-performance.se" { + type master; + file "sth.ip-performance.se"; + notify yes; + allow-transfer { 87.76.255.2; }; +}; + +// linknett +zone "0.76.87.in-addr.arpa" { + type master; + file "0.76.87.in-addr.arpa"; + notify yes; + allow-transfer { 87.76.255.2; 193.0.0.0/22; }; +}; + // linknett zone "174.76.87.in-addr.arpa" { type master; @@ -88,6 +104,13 @@ zone "76.87.in-addr.arpa" { file "dynamic/76.87.in-addr.arpa"; allow-transfer { 194.19.3.20; 87.76.255.2; 193.0.0.0/22; }; }; +zone "f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa" { + type master; + allow-update { key DHCP_UPDATER; }; + notify yes; + file "dynamic/f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa"; + allow-transfer { 194.19.3.20; 87.76.255.2; }; +}; EOF diff --git a/config/make-port-config.pl b/config/make-port-config.pl index 893d4f4..6b3ba33 100755 --- a/config/make-port-config.pl +++ b/config/make-port-config.pl @@ -1,7 +1,8 @@ #! /usr/bin/perl open PATCHLIST, ") { chomp; @@ -28,24 +29,27 @@ while () { my $vlan = "$row$switch"; my $ipv6 = sprintf "F%02u%u", $row, $switch; - $distros{$distro} .= <<"EOF"; + $vlans{$distro} .= <<"EOF"; vlan $vlan name $name ! +EOF + + $ports{$distro} .= <<"EOF"; default interface vlan $vlan interface vlan $vlan description $name ip address $ip 255.255.255.192 - ip directed-broadcast 10 + ip directed-broadcast 101 ip helper-address 87.76.254.2 no ip proxy-arp ip access-group great-wall-of-tg in ipv6 address 2001:16D8:FFFF:${ipv6}::1/64 - ip igmp version 3 + ip igmp version 2 ip pim sparse-mode no shutdown + exit ! - default interface $port interface $port description $name @@ -57,14 +61,20 @@ interface $port storm-control broadcast level 2 no shutdown + exit ! EOF } -for my $distro (keys %distros) { +for my $distro (keys %vlans) { open DISTRO, ">$distro-config" or die "$distro-config: $!"; - print DISTRO $distros{$distro}; + print DISTRO <<"EOF"; +access-list 101 remark ip directed broadcast +access-list 101 permit ip any any dscp cs7 +EOF + print DISTRO $vlans{$distro}; + print DISTRO $ports{$distro}; print DISTRO "end\n"; close DISTRO; } diff --git a/make-all-config.sh b/make-all-config.sh index 276a4d4..1db0af2 100755 --- a/make-all-config.sh +++ b/make-all-config.sh @@ -11,7 +11,7 @@ cat static-switches.txt >> switches.txt scp mbd-ports *-config sesse@f1:/tftpboot/portcfg/ # regenerate the mbd netlist -(echo '# Autogenerated. Do not touch!' ; echo "package Config;"; echo 'our @networks = (' ; cut -d" " -f1-2 switches.txt | perl -e 'while (<>) { chomp; my ($net,$mask) = split / /; print "\t\"$net/$mask\",\n"; }' ; echo ');' ; echo '1;') > mbd/nets.pl +(echo '# Autogenerated. Do not touch!' ; echo "package Config;"; echo 'our @networks = (' ; cut -d" " -f1-2 switches.txt | grep -vE '87\.76\.(130|131|216)\.0' | perl -e 'while (<>) { chomp; my ($net,$mask) = split / /; print "\t\"$net/$mask\",\n"; }' ; echo ');' ; echo '1;') > mbd/nets.pl perl web/make-switches.pl > switches.sql scp switches.sql root@space: diff --git a/mbd/access_list.pl b/mbd/access_list.pl index 137f173..57ae614 100644 --- a/mbd/access_list.pl +++ b/mbd/access_list.pl @@ -4,6 +4,7 @@ package Config; our @access_list = ( # half-life - untested (packet dump only) { + name => 'Half-Life', ports => [ 27015 ], sizes => [ 16 ] }, @@ -11,18 +12,21 @@ our @access_list = ( # cs 1.6 - verified # (funker muligens for _alle_ source-spill inkl. hl2/cs:s) { + name => 'CS 1.6, other Source games', ports => [ 4242, "26900..26905", "27015..27020" ], sizes => [ 25 ] }, # doom 3 - verified { + name => 'Doom 3', ports => [ "27666..27673" ], sizes => [ 14 ] }, # quake 1 - verified { + name => 'Quake 1', ports => [ 26000 ], sizes => [ 12 ] }, @@ -30,6 +34,7 @@ our @access_list = ( # q3a - tested with demo only # rtcw: enemy territory - untested (packet dump only) { + name => 'Quake 3 Arena, RTCW: ET', ports => [ "27960..27969" ], sizes => [ 15 ] }, @@ -37,30 +42,35 @@ our @access_list = ( # bf2 - tested with demo only # bf2142 reportedly uses same engine { + name => 'BF2/BF2142', ports => [ "29900..29950" ], sizes => [ 8 ] }, # bf1942 - unverified (packet dump only) { + name => 'BF1942', ports => [ "22000..22010" ], sizes => [ 8 ] }, # quake 4 - tested with demo only, MUST select "internet" { + name => 'Quake 4', ports => [ 27950, 28004 ], sizes => [ 14 ] }, # quake 2 - untested (packet dump only) { + name => 'Quake 2', ports => [ 27910 ], sizes => [ 11 ] }, # warcraft 3 - untested (packet dump only) { + name => 'Warcraft 3', ports => [ "6112..6119" ], sizes => [ 16, 48 ], filter => sub { return (ord(substr(shift, 1, 1)) == 0x2f); } @@ -68,30 +78,35 @@ our @access_list = ( # ut2003/ut2004 - untested (packet dump only) { + name => 'UT2003/UT2004', ports => [ 10777 ], sizes => [ 5 ] }, # soldat - untested (packet dump only) { + name => 'Soldat', ports => [ 23073 ], sizes => [ 8 ] }, # starcraft - untested (packet dump only) { + name => 'Starcraft', ports => [ 6111, 6112 ], sizes => [ 8, 20 ] }, # trackmania nations - untested (packet dump only) { + name => 'Trackmania Nations', ports => [ "2350..2370" ], sizes => [ 42 ] }, # company of heroes - untested (packet dump only) { + name => 'Company of Heroes', ports => [ 9100 ], sizes => [ 39 ] }, @@ -99,8 +114,17 @@ our @access_list = ( # command & conquer 3 - untested (packet dump only, reported to have some kind # of chat functionality) { + name => 'Command & Conquer 3', ports => [ "8086..8093" ], - sizes => [ 476 ] + sizes => [ 476 ], + filter => sub { return 0; } + }, + + # openttd + { + name => 'OpenTTD', + ports => [ 3979 ], + sizes => [ 3 ] }, # unreal tournament, port 9777? diff --git a/mbd/mbd.pl b/mbd/mbd.pl index 7fcc8d8..4900c1b 100644 --- a/mbd/mbd.pl +++ b/mbd/mbd.pl @@ -4,9 +4,17 @@ use warnings; use Socket; use Net::CIDR; use Net::RawIP; +use Time::HiRes; require './access_list.pl'; require './nets.pl'; +require './survey.pl'; require './mbd.pm'; +use lib '../include'; +use nms; +use strict; +use warnings; + +my ($dbh, $q); sub fhbits { my $bits = 0; @@ -16,9 +24,38 @@ sub fhbits { return $bits; } +# used for rate limiting +my %last_sent = (); + +# for own surveying +my %active_surveys = (); +my %last_survey = (); + +my %cidrcache = (); +sub cache_cidrlookup { + my ($addr, $net) = @_; + my $key = $addr . " " . $net; + + if (!exists($cidrcache{$key})) { + $cidrcache{$key} = Net::CIDR::cidrlookup($addr, $net); + } + return $cidrcache{$key}; +} + +my %rangecache = (); +sub cache_cidrrange { + my ($net) = @_; + + if (!exists($rangecache{$net})) { + ($rangecache{$net}) = Net::CIDR::cidr2range($net); + } + + return $rangecache{$net}; +} + open LOG, ">>", "mbd.log"; -my @ports = mbd::find_all_ports(); +my @ports = ( mbd::find_all_ports() , $Config::survey_port_low .. $Config::survey_port_high ); # Open a socket for each port my @socks = (); @@ -40,6 +77,29 @@ while (1) { my $rout; my $nfound = select($rout=$rin, undef, undef, undef); + my $now = [Time::HiRes::gettimeofday]; + + # First of all, close any surveys that are due. + for my $sport (keys %active_surveys) { + my $age = Time::HiRes::tv_interval($active_surveys{$sport}{start}, $now); + if ($age > $Config::survey_time && $active_surveys{$sport}{active}) { + print "Survey for '" . $Config::access_list[$active_surveys{$sport}{entry}]->{name} . "'/" . + $active_surveys{$sport}{dport} . ": " . $active_surveys{$sport}{num} . " active servers.\n"; + $active_surveys{$sport}{active} = 0; + + # (re)connect to the database if needed + if (!defined($dbh) || !$dbh->ping) { + $dbh = nms::db_connect(); + $q = $dbh->prepare("INSERT INTO mbd_log (ts,game,port,description,active_servers) VALUES (CURRENT_TIMESTAMP,?,?,?,?)") + or die "Couldn't prepare query"; + } + $q->execute($active_surveys{$sport}{entry}, $active_surveys{$sport}{dport}, $Config::access_list[$active_surveys{$sport}{entry}]->{name}, $active_surveys{$sport}{num}); + } + if ($age > $Config::survey_time * 3.0) { + delete $active_surveys{$sport}; + } + } + for my $sock (@socks) { next unless (vec($rout, fileno($sock), 1) == 1); @@ -48,11 +108,40 @@ while (1) { my ($sport, $saddr) = sockaddr_in($addr); my ($dport, $daddr) = sockaddr_in(getsockname($sock)); my $size = length($data); + + # Check if this is a survey reply + if ($dport >= $Config::survey_port_low && $dport <= $Config::survey_port_high) { + if (!exists($active_surveys{$dport})) { + print "WARNING: Unknown survey port $dport, ignoring\n"; + next; + } + if (!$active_surveys{$dport}{active}) { + # remains + next; + } + + ++$active_surveys{$dport}{num}; + next; + } + + # Rate limiting + if (exists($last_sent{$saddr}{$dport})) { + my $elapsed = Time::HiRes::tv_interval($last_sent{$saddr}{$dport}, $now); + if ($elapsed < 1.0) { + print LOG "$dport $size 2\n"; + print inet_ntoa($saddr), ", $dport, $size bytes => rate-limited ($elapsed secs since last)\n"; + next; + } + } + # We don't get the packet's destination address, but I guess this should do... # Check against the ACL. my $pass = 0; + my $entry = -1; for my $rule (@Config::access_list) { + ++$entry; + next unless (mbd::match_ranges($dport, $rule->{'ports'})); next unless (mbd::match_ranges($size, $rule->{'sizes'})); @@ -67,19 +156,70 @@ while (1) { print LOG "$dport $size $pass\n"; if (!$pass) { - print "$dport, $size bytes => filtered\n"; + print inet_ntoa($saddr), ", $dport, $size bytes => filtered\n"; + next; } - next unless $pass; + $last_sent{$saddr}{$dport} = $now; - for my $net (@Config::networks) { - next if (Net::CIDR::cidrlookup(inet_ntoa($saddr), $net)); + # The packet is OK! Do we already have a recent enough survey + # for this port, or should we use this packet? + my $survey = 1; + if (exists($last_survey{$entry . "/" . $dport})) { + my $age = Time::HiRes::tv_interval($last_survey{$entry . "/" . $dport}, $now); + if ($age < $Config::survey_freq) { + $survey = 0; + } + } + + # New survey; find an unused port + my $survey_sport; + if ($survey) { + for my $port ($Config::survey_port_low..$Config::survey_port_high) { + if (!exists($active_surveys{$port})) { + $survey_sport = $port; + + $active_surveys{$port} = { + start => $now, + active => 1, + dport => $dport, + entry => $entry, + num => 0 + }; + $last_survey{$entry . "/" . $dport} = $now; + + last; + } + } - my ($range) = Net::CIDR::cidr2range($net); + if (!defined($survey_sport)) { + print "WARNING: no free survey source ports, not surveying.\n"; + $survey = 0; + } + } + + my $num_nets = 0; + for my $net (@Config::networks) { + my ($range) = cache_cidrrange($net); $range =~ /-(.*?)$/; my $broadcast = $1; - print inet_ntoa($saddr), ", $dport, $size bytes => $broadcast\n"; + if ($survey) { + $sendsock->set({ + ip => { + saddr => $Config::survey_ip, + daddr => $broadcast + }, + udp => { + source => $survey_sport, + dest => $dport, + data => $data + } + }); + $sendsock->send; + } + + next if (cache_cidrlookup(inet_ntoa($saddr), $net)); $sendsock->set({ ip => { @@ -93,6 +233,14 @@ while (1) { } }); $sendsock->send; + + ++$num_nets; + } + + if ($survey) { + print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks) [+survey from port $survey_sport]\n"; + } else { + print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks)\n"; } } } diff --git a/mbd/survey.pl b/mbd/survey.pl new file mode 100644 index 0000000..a948180 --- /dev/null +++ b/mbd/survey.pl @@ -0,0 +1,10 @@ +package Config; + +our $survey_ip = "87.76.254.2"; +our $survey_port_low = 60100; +our $survey_port_high = 60200; +our $survey_freq = 60.0; +our $survey_time = 10.0; + +1; + diff --git a/static-switches.txt b/static-switches.txt index 2619cd7..d53a9b5 100644 --- a/static-switches.txt +++ b/static-switches.txt @@ -11,7 +11,7 @@ 87.76.207.0 24 auditorium 87.76.208.0 24 ute 87.76.209.0 24 infodesk -87.76.210.0 24 game-server +87.76.211.0 24 qpad-scene 87.76.212.0 24 game-client 87.76.213.0 24 logistics 87.76.215.0 24 security @@ -19,5 +19,6 @@ 87.76.220.0 24 fugleberget 87.76.222.0 24 democrew 87.76.223.0 24 cam +87.76.224.0 24 chillout 87.76.250.0 24 noc 87.76.252.0 24 presse diff --git a/web/make-switches.pl b/web/make-switches.pl index e1d3fe9..9283546 100644 --- a/web/make-switches.pl +++ b/web/make-switches.pl @@ -11,9 +11,6 @@ print "SELECT pg_catalog.setval('polls_poll_seq', 1, false);\n"; open PATCHLIST, "patchlist.txt" or die "patchlist.txt: $!"; -my $cc = 241; -my $dd = 0; - my $i = 1; while () { chomp; @@ -46,24 +43,31 @@ while () { my $xx = $x + 12; my $yy = $y + (($s > 3) ? 50 : 48); - $dk = $dd + 7 + ($cc - 241) * 42; - -# lasses magic-factor =) - $dk += 4; - if ($dk > 13) { - $dk += 3; - } + my ($ip, $range); + if ($s == 1) { + $ip = "87.76." . ($e) . ".2"; + $range = "87.76." . ($e) . ".0"; + } elsif ($s == 2) { + $ip = "87.76." . ($e) . ".66"; + $range = "87.76." . ($e) . ".64"; + } elsif ($s == 3) { + $ip = "87.76." . ($e) . ".130"; + $range = "87.76." . ($e) . ".128"; + } elsif ($s == 4) { + $ip = "87.76." . ($e + 1) . ".2"; + $range = "87.76." . ($e + 1) . ".0"; + } elsif ($s == 5) { + $ip = "87.76." . ($e + 1) . ".66"; + $range = "87.76." . ($e + 1) . ".64"; + } elsif ($s == 6) { + $ip = "87.76." . ($e + 1) . ".130"; + $range = "87.76." . ($e + 1) . ".128"; + } - print "insert into switches (ip, sysname, switchtype) values ('87.76.$cc.$dk', 'e$e-${s}sw', 'es3024');\n"; + print "insert into switches (ip, sysname, switchtype) values ('$ip', 'e$e-${s}sw', 'es3024');\n"; print "insert into placements (switch, placement) values ($i, box '(($x,$y),($xx,$yy))');\n"; print "insert into dhcp (switch, network) values ($i, '87.76.$c.$d/26');\n"; $i++; - - $dd++; - if ($dd == 42) { - $cc++; - $dd = 0; - } } print "end;\n";