📄 turtlefirewall.pm
字号:
## TurtleFirewall: Turtle Firewall Library## Software per la configurazione di un firewall linux (iptables)## 2002/02/12 11:27:00##======================================================================# Copyright (c) 2001-2006 Andrea Frigido# You may distribute under the terms of either the GNU General Public# License#======================================================================## Changelog:#package TurtleFirewall;use XML::Parser;# Turtle Firewall Versionsub Version { return '1.37';}sub new { my $this ={}; #$this->{NOME} = undef; $this->{fw} = (); $this->{fwItems} = (); $this->{fwKeys} = (); $this->{fw_file} = ''; $this->{fwservices_file} = ''; $this->{userdef_fwservices_file} = ''; $this->{log_limit} = undef; $this->{log_limit_burst} = undef; bless $this; return $this}### Public method for get firewall info (after LoadFirewall)sub GetZoneList { my $this = shift; return sort( keys %{ $this->{fw}{ZONE} } );}sub GetNetList { my $this = shift; return sort( keys %{ $this->{fw}{NET} } );}sub GetHostList { my $this = shift; return sort( keys %{ $this->{fw}{HOST} } );}sub GetGroupList { my $this = shift; return @{$this->{fwKeys}{GROUP}};}sub GetZone { my ($this,$name) = @_; return %{ $this->{fw}{ZONE}{$name} };}sub GetNet { my ($this,$name) = @_; return %{ $this->{fw}{NET}{$name} };}sub GetHost { my ($this,$name) = @_; return %{ $this->{fw}{HOST}{$name} };}sub GetGroup { my ($this,$name) = @_; return %{ $this->{fw}{GROUP}{$name} };}sub GetAllItemsList { my $this = shift; return sort( keys %{ $this->{fwItems} } );}# GetItemsAllowToGroup( group )# Get items allow to inserted into the group: all items defined before the groupsub GetItemsAllowToGroup { my $this = shift; my $group = shift; my @items = (); push @items, 'FIREWALL'; push @items, @{$this->{fwKeys}{ZONE}}; push @items, @{$this->{fwKeys}{NET}}; push @items, @{$this->{fwKeys}{HOST}}; foreach my $g ( @{$this->{fwKeys}{GROUP}} ) { if( $g eq $group ) { last; } push @items, $g; } return @items;}sub GetServicesList { my $this = shift; return sort( keys %{ $this->{services} } );}sub GetService { my $this = shift; my $name = shift; return %{ $this->{services}{$name} };}sub GetMasqueradesCount { my $this = shift; return $#{$this->{fw}{MASQUERADE}}+1;}sub GetMasquerade { # param n = id of masquerade rule (1 .. MasqueradeCount) my ($this,$n) = @_; return %{ $this->{fw}{MASQUERADE}[$n-1] };}sub GetNatsCount { my $this = shift; return $#{$this->{fw}{NAT}}+1;}sub GetNat { my ($this,$n) = @_; return %{ $this->{fw}{NAT}[$n-1] };}sub GetRedirectCount { my $this = shift; return $#{$this->{fw}{REDIRECT}}+1;}sub GetRedirect { my ($this,$n) = @_; return %{ $this->{fw}{REDIRECT}[$n-1] };}sub GetRulesCount { my $this = shift; return $#{$this->{fw}{RULE}}+1;}sub GetRule { my ($this,$n) = @_; return %{ $this->{fw}{RULE}[$n-1] };}# Get Firewall Configuration Specific Optionsub GetOption { my ($this,$name) = @_; return $this->{fw}{OPTION}{$name};}# AddGroup( $group, $description, @items );sub AddGroup { my $this = shift; my $group = shift; my $description = shift; my @items = @_; if( !$this->{fw}{GROUP}{$group} ) { # Se non e' gia' stato inserito lo aggiungo alla lista ordinata di keys push @{ $this->{fwKeys}{GROUP} }, $group; } %{ $this->{fw}{GROUP}{$group} } = ( 'DESCRIPTION'=>$description ); @{ $this->{fw}{GROUP}{$group}{ITEMS} } = @items; $this->{fwItems}{$group} = 'GROUP'; return 1;}# AddHost( $name, $ip, $mac, $zone, $description )sub AddHost { my ($this, $name, $ip, $mac, $zone, $description) = @_; %{ $this->{fw}{HOST}{$name} } = ('NAME'=>$name, 'IP'=>$ip, 'MAC'=>$mac, 'ZONE'=>$zone, 'DESCRIPTION'=>$description ); $this->{fwItems}{$name} = 'HOST';}# AddNet( $name, $ip, $netmask, $zone, $description )sub AddNet { my ($this, $name, $ip, $netmask, $zone, $description) = @_; %{ $this->{fw}{NET}{$name} } = ('NAME'=>$name, 'IP'=>$ip, 'NETMASK'=>$netmask,'ZONE'=>$zone, 'DESCRIPTION'=>$description ); $this->{fwItems}{$name} = 'NET'; return 1;}# AddZone( $name, $if, $description )sub AddZone { my ($this, $name, $if, $description) = @_; %{ $this->{fw}{ZONE}{$name} } = ('NAME'=>$name, 'IF'=>$if, 'DESCRIPTION'=>$description ); $this->{fwItems}{$name} = 'ZONE'; return 1;}# AddMasquerade( $idx, $zone, $active ) if $idx==0 then add new Masqueradesub AddMasquerade { my ($this, $idx, $src, $dst, $service, $port, $masquerade, $active ) = @_; my %attr = ( 'SRC'=>$src, 'DST'=>$dst, 'SERVICE'=>$service); if( $port ne '' ) { $attr{PORT} = $port; } if( ! $masquerade ) { $attr{MASQUERADE} = 'NO'; } if( ! $active ) { $attr{ACTIVE} = 'NO'; } $this->AddMasqueradeAttr( $idx, %attr );}sub AddMasqueradeAttr { my $this = shift; my $idx = shift; my %attr = @_; if( $idx == 0 ) { %{ $this->{fw}{MASQUERADE}[$#{$this->{fw}{MASQUERADE}}+1] } = %attr; } else { %{ $this->{fw}{MASQUERADE}[$idx-1] } = %attr; }}# AddNat( $idx, $virtual, $real, $service, $port, $active ) if $idx==0 then add new Masqueradesub AddNat { my ($this, $idx, $virtual, $real, $service, $port, $active) = @_; my %attr = ('VIRTUAL'=>$virtual, 'REAL'=>$real); if( $service ne '' ) { $attr{SERVICE} = $service; } if( $port ne '' ) { $attr{PORT} = $port; } if( ! $active ) { $attr{ACTIVE} = 'NO'; } $this->AddNatAttr( $idx, %attr );}sub AddNatAttr { my $this = shift; my $idx = shift; my %attr = @_; if( $idx == 0 ) { %{ $this->{fw}{NAT}[$#{$this->{fw}{'NAT'}}+1] } = %attr; } else { %{ $this->{fw}{NAT}[$idx-1] } = %attr; }}# AddRedirect( $idx, $src, $dst, $service, $port, $toport, $active );sub AddRedirect { my ($this, $idx, $src, $dst, $service, $port, $toport, $redirect, $active ) = @_; my %attr = ( 'SRC'=>$src, 'DST'=>$dst, 'SERVICE'=>$service); if( $port ne '' ) { $attr{PORT} = $port; } if( $toport ne '' ) { $attr{TOPORT} = $toport; } if( ! $redirect ) { $attr{REDIRECT} = 'NO'; } if( ! $active ) { $attr{ACTIVE} = 'NO'; } $this->AddRedirectAttr( $idx, %attr );}sub AddRedirectAttr { my $this = shift; my $idx = shift; my %attr = @_; if( $idx == 0 ) { %{$this->{fw}{'REDIRECT'}[$#{$this->{fw}{'REDIRECT'}}+1]} = %attr; } else { %{$this->{fw}{'REDIRECT'}[$idx-1]} = %attr; }}# AddRule( $idx, $src, $dst, $service, $port, $target, $mark, $active, $description );sub AddRule { my ($this, $idx, $src, $dst, $service, $port, $target, $mark, $active, $description ) = @_; my %attr = ( 'SRC'=>$src, 'DST'=>$dst, 'SERVICE'=>$service); if( $target ne '' ) { $attr{TARGET} = $target; } if( $port ne '' ) { $attr{PORT} = $port; } if( $mark ne '' ) { $attr{MARK} = $mark; } if( ! $active ) { $attr{ACTIVE} = 'NO'; } if( $description ne '' ) { $attr{DESCRIPTION} = $description; } $this->AddRuleAttr( $idx, %attr );}sub AddRuleAttr { my $this = shift; my $idx = shift; my %attr = @_; if( $idx == 0 ) { %{$this->{fw}{'RULE'}[$#{$this->{fw}{'RULE'}}+1]} = %attr; } else { %{$this->{fw}{'RULE'}[$idx-1]} = %attr; }}sub MoveRule { my ($this, $idxSrc, $idxDst) = @_; my %attr = %{$this->{fw}{RULE}[$idxSrc-1]}; splice @{$this->{fw}{RULE}}, $idxSrc-1, 1; splice @{$this->{fw}{RULE}}, $idxDst-1, 0, \%attr;}# AddOption( $name, $value );sub AddOption { my ($this, $name, $value) = @_; $this->{fw}{OPTION}{$name} = $value;}# DeleteItem( $name );sub DeleteItem { my $this = shift; my $name = shift; my $type = $this->{fwItems}{$name}; # Now I check if this item is included into a group my $found = 0; for my $g (@{$this->{fwKeys}{GROUP}}) { for my $i (@{$this->{fw}{GROUP}{$g}{ITEMS}}) { if( $i eq $name ) { $found = 1; last; } } } # Now I check if this item is used by a rule my $rules = $this->GetRulesCount(); for( my $r=0; $r<$rules; $r++ ) { my %rule = $this->GetRule( $r ); if( $rule{SRC} eq $name || $rule{DST} eq $name ) { $found = 1; last; } } # Now I check if this item is used by a redirect rule my $redirectlist = $this->GetRedirectCount(); for( my $r=0; $r<$redirectlist; $r++ ) { my %redirect = $this->GetRedirect( $r ); if( $redirect{SRC} eq $name || $redirect{DST} eq $name ) { $found = 1; last; } } # Now I check if this item is used by a NAT rule if( $type eq 'HOST' ) { my $nats = $this->GetNatsCount(); for( my $n=0; $n<$nats; $n++ ) { my %nat = $this->GetNat( $n ); if( $nat{VIRTUAL} eq $name || $nat{REAL} eq $name ) { $found = 1; last; } } } # Now I check if this item is used by a masquerade rule my $masqs = $this->GetMasqueradesCount(); for( my $m=0; $m<$masqs; $m++ ) { my %masq = $this->GetMasquerade( $m ); if( $masq{SRC} eq $name || $masq{DST} eq $name ) { $found = 1; last; } } if( !$found ) { delete $this->{fw}{$type}{$name}; delete $this->{fwItems}{$name}; my @newKeys = (); for my $k (@{$this->{fwKeys}{$type}}) { if( $k ne $name ) { push @newKeys, $k; } } @{$this->{fwKeys}{$type}} = @newKeys; return 1; } else { return 0; }}sub RenameItem { my $this = shift; my ($oldname, $newname) = @_; if( $oldname eq '' || $newname eq '' || $this->{fwItems}{$newname} ne '' || $newname eq 'FIREWALL' ) { # An Item with this name exists return 0; } else { $type = $this->{fwItems}{$oldname}; %{$this->{fw}{$type}{$newname}} = %{$this->{fw}{$type}{$oldname}}; $this->{fw}{$type}{$newname}{NAME} = $newname; $this->{fwItems}{$newname} = $type; delete $this->{fw}{$type}{$oldname}; delete $this->{fwItems}{$oldname}; for( my $i=0; $i<=$#{$this->{fwKeys}{$type}}; $i++ ) { if( $this->{fwKeys}{$type}[$i] eq $oldname ) { $this->{fwKeys}{$type}[$i] = $newname; } } # If it's a zone, I need to change all items that use this zone. if( $type eq 'ZONE' ) { foreach $k (@{$this->{fwKeys}{HOST}}) { if( $this->{fw}{HOST}{$k}{ZONE} eq $oldname ) { $this->{fw}{HOST}{$k}{ZONE} = $newname; } } foreach $k (@{$this->{fwKeys}{NET}}) { if( $this->{fw}{NET}{$k}{ZONE} eq $oldname ) { $this->{fw}{NET}{$k}{ZONE} = $newname; } } } # change itme name in groups foreach my $group (@{$this->{fwKeys}{GROUP}}) { for( my $i=0; $i<=$#{$this->{fw}{GROUP}{$group}{ITEMS}}; $i++ ) { if( $this->{fw}{GROUP}{$group}{ITEMS}[$i] eq $oldname ) { $this->{fw}{GROUP}{$group}{ITEMS}[$i] = $newname; } } } # Change item name in all rules foreach my $ruletype ('RULE','NAT','MASQUERADE','REDIRECT') { for( my $i=0; $i<=$#{$this->{fw}{$ruletype}}; $i++ ) { foreach $field ('SRC','DST','ZONE','VIRTUAL','REAL') { if( $this->{fw}{$ruletype}[$i]{$field} eq $oldname ) { $this->{fw}{$ruletype}[$i]{$field} = $newname; } } } } return 1; }}# DeleteGroup( $group );sub DeleteGroup { my ($this, $group) = @_; return $this->DeleteItem( $group );}# DeleteHost( $host );sub DeleteHost { my ($this, $host) = @_; return $this->DeleteItem( $host );}# DeleteHost( $net );sub DeleteNet { my ($this, $net) = @_; return $this->DeleteItem( $net );}# DeleteZone( $zone );sub DeleteZone { my ($this, $zone) = @_; return $this->DeleteItem( $zone );}# DeleteMasquerade( $idx );sub DeleteMasquerade { my ($this, $idx) = @_; splice( @{$this->{fw}{'MASQUERADE'}}, $idx-1, 1 );}# DeleteNat( $idx );sub DeleteNat { my ($this, $idx) = @_; splice( @{$this->{fw}{'NAT'}}, $idx-1, 1 );}# DeleteRedirect( $idx );sub DeleteRedirect { my ($this, $idx) = @_; splice( @{$this->{fw}{'REDIRECT'}}, $idx-1, 1 );}# DeleteRule( $idx );sub DeleteRule { my ($this, $idx) = @_; splice( @{$this->{fw}{'RULE'}}, $idx-1, 1 );}# DeleteOption( $name );sub DeleteOption { my ($this, $name) = @_; delete $this->{fw}{OPTION}{$name};}#===================================# Carico le regole del firewall#==================# Load Firewall Items and rules.sub LoadFirewall { my $this = shift; my $fwFile = shift; $this->{fw_file} = $fwFile; # Aggiungo il firewall come zona predefinita $this->{fwItems}{FIREWALL} = 'ZONE'; %{$this->{fw}{ZONE}{FIREWALL}} = (NAME=>'FIREWALL'); my $xml = new XML::Parser( Style=>'Tree' ); my @tree = @{ $xml->parsefile( $fwFile ) }; #------ # Ciclo sui tag di primo livello (firewall) for( my $i=0; $i<=$#tree; $i+=2 ) { my $name = uc($tree[$i]); if ($name eq 'FIREWALL') { my @list = @{$tree[$i+1]}; my %attr = shift @list; #------ # Ciclo sui tag di secondo livello (hosts, groups, rules ecc.) for( my $j=0; $j<=$#list; $j+=2 ) { my $name2 = uc($list[$j]); if( $name2 eq 'ZONE' ) { $this->_LoadFirewallItem( 'ZONE', @{$list[$j+1]} ); } if( $name2 eq 'NET' ) { $this->_LoadFirewallItem( 'NET', @{$list[$j+1]} ); } if( $name2 eq 'HOST' ) { $this->_LoadFirewallItem( 'HOST', @{$list[$j+1]} ); } if( $name2 eq 'GROUP' ) { $this->_LoadFirewallItem( 'GROUP', @{$list[$j+1]} ); } if( $name2 eq 'MASQUERADE' ) { $this->_LoadFirewallNat( 'MASQUERADE', @{$list[$j+1]} ); } if( $name2 eq 'NAT' ) { $this->_LoadFirewallNat( 'NAT', @{$list[$j+1]} ); } if( $name2 eq 'REDIRECT' ) { $this->_LoadFirewallNat( 'REDIRECT', @{$list[$j+1]} ); } if( $name2 eq 'RULE' ) { $this->_LoadFirewallRule( @{$list[$j+1]} ); } if( $name2 eq 'OPTIONS' ) { $this->_LoadFirewallOptions( @{$list[$j+1]} ); } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -