Hi,
This is crazy use of perl. This work as pure network bridge which routing based on mac-adress. Performance is realy very good 1.2ms for flood ping. I test it only on linux with 2 NICs :-)
there is 3 programs :0)
2 - sending packet from eth0(eth1) to local device lo
1 - receive packet from lo, filtering baseon mac or ip, do route based on mac and learned mac-interface table, and finaly show some statistics.Writing of statistics is very slow and Idu it every 10s :-) but performance is going down while writing to screen :-)
#!/usr/bin/perl # program which send data from eth0 to lo # I call it eth0 use Socket 1.3; use Net::Pcap; use strict; no utf8; socket(RAW,17, 3, 255) || die $!; binmode (RAW); my $iface = 'eth0'; my $ifaceid = pack ('n',2); my $flags = pack("SniC12",17,0,1,0); my ($err); my $pcap_eth = Net::Pcap::open_live($iface, 1524, 1, 0, \$err); if (!defined($pcap_eth)) { die ("Error opening device eth0 returned error $err\n"); } Net::Pcap::loop ($pcap_eth,-1,\&process,undef); sub process{ send(RAW,$ifaceid.$_[2],0,$flags) || die "Send :$!\n"; }
this is same as previous
#!/usr/bin/perl # This one sends packet from eth1 to lo # I call it eth1 use Socket 1.3; use Net::Pcap; use strict; no utf8; socket(RAW,17, 3, 255) || die $!; binmode (RAW); my $iface = 'eth1'; my $ifaceid = pack ('n',3); my $flags = pack("SniC12",17,0,1,0); my ($err); my $pcap_eth = Net::Pcap::open_live($iface, 1524, 1, 0, \$err); if (!defined($pcap_eth)) { die ("Error opening device eth0 returned error $err\n"); } Net::Pcap::loop ($pcap_eth,-1,\&process,undef); sub process{ #I add interface id to packe to identify source interface send(RAW,$ifaceid.$_[2],0,$flags) || die "Send :$!\n"; }

Finaly the main bridge software :-)))
#!/usr/bin/perl use Socket 1.3; #use Data::Dumper; #use Data::Hexdumper; #use NetPacket; use NetPacket::IP; use NetPacket::ARP; use Net::Pcap; use Time::HiRes qw( gettimeofday tv_interval); use strict; no utf8; #define SOCKET_PACKET socket(RAW,17, 3, 255) || die $!; binmode (RAW); #setup sniffer my ($err); my $pcap_eth = Net::Pcap::open_live('lo', 1524, 1, 0, \$err); if (!defined($pcap_eth)) { die ("Error opening device eth0 returned error $err\n"); } #load block maps my $blockip={}; loadip(); my $blockmac = {}; loadmac(); sleep 1; my $clear = `clear`; #statistic my $stat = { eth0 => 0, eth1 => 0, 'eth1->eth0' => 0, 'eth0->eth1' => 0, macdrop => 0, ipdrop => 0, total => 0, sum => 0, }; #define global vars my $debug=1; my $tabletime=10; my $delta = 5; my $arptable = {}; my $last = 0; my $protoname = { 2048 => 'ip', 2054 => 'arp', }; #start working Net::Pcap::loop ($pcap_eth,-1,\&process,undef); ###################################################################### ### Process sniffed packet ###################################################################### sub process { my $t0 = [gettimeofday]; my (undef,$hdr,$ipkt) = @_; #decode source interface my ($srciface,$pkt)=unpack('na*',$ipkt); return if ($srciface > 3 || $srciface<2); $stat->{total}++; #decode Layer-2 my ($dstmac,$srcmac,$proto,$data)=unpack('H12H12na*',$pkt); #block on Layer-2 if ($blockmac->{$dstmac} == 1 || $blockmac->{$srcmac} == 1) { $stat->{macdrop}++; $stat->{sum}+= tv_interval ($t0); return; } #block on Layer-3 proto IP,ARP if (blockip($proto,$data) == 1) { $stat->{ipdrop}++; $stat->{sum}+= tv_interval ($t0); return; } #do route and send my $ret = route ($dstmac,$srcmac,$srciface,$pkt); $stat->{eth0}+= $ret if ($srciface == 2); $stat->{eth1}+= $ret if ($srciface == 3); #elapsed time $stat->{sum}+= tv_interval ($t0); #cleanup arp tables every 10sec my $time = time; if ($last<$time) { cleanup($time); showstat(); } } ###################################################################### ### Route based on ETH - MAC ###################################################################### sub route ($$$) { my ($dstmac,$srcmac,$srciface,$pkt) = @_; #temoprary time to don't nedd call function time my $time=time; #check for duplicity of packet if (defined ($arptable->{$srcmac}->{iface}) && $arptable->{$srcmac +}->{iface} != $srciface) { return 0; } $arptable->{'ffffffffffff'} = undef; $arptable->{$srcmac}={ 'time' => ($time+$tabletime), iface => $srciface, }; my $dstiface; #check route in table and validity if ($arptable->{$dstmac}->{'time'} > $time) { $dstiface = $arptable->{$dstmac}->{iface}; }else{ #if not longer valid remove $dstiface=undef; $arptable->{$dstmac}=undef; } #return if same interface do nothing return 1 if ($dstiface == $srciface); #if valid send to destination if ($dstiface == 2 || $dstiface == 3){ send(RAW,$pkt,0,pack("SniC12",17,0,$dstiface,0)) || die "Send +:$!\n"; $stat->{'eth0->eth1'}++ if ($srciface == 2); $stat->{'eth1->eth0'}++ if ($srciface == 3); #else send to all except src; }else{ if ($srciface == 2) { $stat->{'eth0->eth1'}++; send(RAW,$pkt,0,pack("SniC12",17,0,3,0)) || die "Send :$!\ +n"; }elsif ($srciface == 3) { $stat->{'eth1->eth0'}++; send(RAW,$pkt,0,pack("SniC12",17,0,2,0)) || die "Send :$!\ +n"; }; } return 1; } ###################################################################### ### Block IP adress ###################################################################### sub blockip { my ($proto,$data) = @_; #decode Layer-3 if ($proto eq 0x0806) { my $arp = NetPacket::ARP->decode($data); return 1 if ($blockip->{$arp->{spa}} == 1); return 1 if ($blockip->{$arp->{tpa}} == 1); }elsif ($proto eq 0x0800) { my $ip = NetPacket::IP->decode($data); return 1 if ($blockip->{$ip->{src_ip}} == 1); return 1 if ($blockip->{$ip->{dest_ip}} == 1); } } ###################################################################### ### Visual & Cleanup Utils ###################################################################### sub show { print STDERR Data::Hexdumper::hexdump (data => $_[0]); } sub showarp { print "Mac Interface validity\n"; print "-------------------------------\n"; my $time = time; my $ifacename = { 2 => 'eth0', 3 => 'eth1', }; foreach my $key(sort (keys %{$arptable})){ my $valid = $arptable->{$key}->{'time'}-$time; next if ($valid<0); print "$key\t".$ifacename->{$arptable->{$key}->{iface}}."\t$va +lid s\n"; } } sub cleanup { my $time = shift; foreach my $key( keys %{$arptable}){ $arptable->{$key}= undef if ($arptable->{$key}->{'time'}<$time +); } $last = $time+$delta; } sub showstat { print $clear."\n"; print "Network stats\n"; print "eth0\teth1\teth0->eth1\teth1->eth0\tdropmac\tdropip\n"; print $stat->{eth0}."\t".$stat->{eth1}."\t".$stat->{'eth0->eth1'}. +"\t\t".$stat->{'eth1->eth0'}."\t\t".$stat->{macdrop}."\t".$stat->{ipd +rop}."\n\n"; print "Average proces time: ".(($stat->{sum}/$stat->{total})*1000) +." ms\n\n"; showarp(); } ###################################################################### ### Loading policy files ###################################################################### sub loadmac { #open file with mac adresses open(MAC, './block.mac') || die "Open block.mac: $!\n"; my $block={}; #read echa line from file print "Blocked MACs\n"; while (<MAC>) { #normalize to network type lc $_; s/://gsi; s/\s//gsi; s/\.//gsi; #skip all not valid mac adresses next if ( length ($_)< 12); #add to deny list $blockmac->{$_}=1; print $_."\n"; } close MAC; return; } sub loadip { #open file with mac adresses open(IP, './block.ip') || die "Open block.ip: $!\n"; print "Blocked IPs\n"; #read echa line from file while (<IP>) { #next if to short next if ( length ($_)< 7); #parse IP from file my (@ip) = m/(\d*)\.(\d*)\.(\d*)\.(\d*)/; #convert to binary my $pip = pack ('C4',@ip); $blockip->{$pip}=1; $blockip->{$_}=1; print "$_ \n"; } close IP; return; }
Crazy :-) but works nearly at same speed like C program :-)

PS: Thank's to all monks which helpme with some problems (binmode ;-) -=- MamuT -=-

Replies are listed 'Best First'.
A reply falls below the community's threshold of quality. You may see it by logging in.