⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 turtlefirewall.pm

📁 linux环境下的一个防火墙程序的源代码
💻 PM
📖 第 1 页 / 共 4 页
字号:
	my $is_redirect = $redirect{REDIRECT} ne 'NO';	my $src = $redirect{SRC};	my $dst = $redirect{DST};	# Vedo se come sorgente ho un group	if( $fwItems{$src} eq 'GROUP' ) {		my %newredirect = %redirect;		foreach my $item ( @{$fw{GROUP}{$src}{ITEMS}} ) {			if( $item ne 'FIREWALL' ) {				$newredirect{SRC} = $item;				$rules .= $this->applyRedirect( %newredirect );			}		}		return $rules;	}	# Vedo se come destinazione ho un group	if( $fwItems{$dst} eq 'GROUP' ) {		my %newredirect = %redirect;		foreach my $item ( @{$fw{GROUP}{$dst}{ITEMS}} ) {			# Ignore ZONE items (PREROUTING don't accept -o option)			if( $item ne 'FIREWALL' && $fw{ZONE}{$item}{IF} eq '' ) {				$newredirect{DST} = $item;				$rules .= $this->applyRedirect( %newredirect );			}		}		return $rules;	}	# Definisco il SERVICE	my $service = $redirect{SERVICE};	my $port = $redirect{PORT};	my $toport = $redirect{TOPORT};	my ($src_zone, $src_peer, $src_mac) = $this->expand_item( $src );	my %src_zone_attr = $this->GetZone( $src_zone );	my $src_if = $src_zone_attr{IF};	my $dst_zone;	my $dst_peer;	my $dst_if;	if( $dst eq '*' ) {		$dst_zone = '*';		$dst_peer = '0.0.0.0/0';		$dst_if = '';	} else {		($dst_zone, $dst_peer) = $this->expand_item( $dst );		my %dst_zone_attr = $this->GetZone( $dst_zone );		$dst_if = $dst_zone_attr{IF};	}	print $is_redirect ? '' : 'NOT ',"REDIRECT ( service $service";	if( $service eq 'tcp' || $service eq 'udp' ) { print "($port)"; }	print " $src";	if( $src_mac ne '' ) { print "(mac:$src_mac)"; }	print " --> $dst )";	if( $is_redirect ) {		 print " TO LOCAL PORT $toport";	}	print "\n";	# Creo le 2 catene di andata e ritorno.	$rules .= $this->applyServiceRedirect( \%services, $service, $src_if, $src_peer, $src_mac, $dst_if, $dst_peer, $port, $toport, $is_redirect);		return $rules;}sub applyServiceRedirect {	my $this = shift;	my %calledServices = ();	return $this->_applyServiceRedirect( \%calledServices, @_ );}sub _applyServiceRedirect {	my $this = shift;	my ($ref_calledServices, $ref_services, $serviceName, $src_if, $src_peer, $src_mac, $dst_if, $dst_peer, $port, $toport, $is_redirect) = @_;	my $rules = '';		my %service = %{$ref_services->{$serviceName}};	$ref_calledServices->{$serviceName} = 1;	# ciclo sulle regole di filering	for( my $i = 0; $i <= $#{$service{FILTERS}}; $i++ ) {		my %filter = %{$service{FILTERS}[$i]};		if( $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) {			# It is a subservice, recursion call to _applyService			$rules .= $this->_applyServiceRedirect( $ref_calledServices, $ref_services, $filter{SERVICE},				$src_if, $src_peer, $src_mac, $dst_if, $dst_peer, $port, $toport, $is_redirect );			next;		}		my $direction = $filter{DIRECTION};		my $p = $filter{P};		my $icmptype = $filter{ICMPTYPE};		my $sport = $filter{SPORT};		my $dport = $filter{DPORT};		my $state = $filter{STATE};		my $jump = $filter{JUMP};		# I only use the first tcp/udp filter rule		if( $direction eq 'go' && ($p eq 'tcp' || $p eq 'udp' || $p eq '') &&		    ($filter{JUMP} eq '' || $filter{JUMP} eq 'ACCEPT') ) {			if( $dport eq 'PORT' ) {				$dport = $port;			}			my $cmd = "-A REDIR ";			if( $src_if ne '' ) { $cmd .= "-i $src_if "; }			if( $src_peer ne '0.0.0.0/0' ) { $cmd .= "-s $src_peer "; }			if( $src_mac =~ /^[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}$/ ) {				$cmd .= "-m mac --source-mac $src_mac ";			}			# iptables prerouting chain don't accept -o option.			#if( $dst_if ne '' ) { $cmd .= "-o $dst_if "; }			if( $dst_peer ne '0.0.0.0/0' ) { $cmd .= "-d $dst_peer "; }			if( $p ne '' ) {				$cmd .= "-p $p ";			} else {				$cmd .= "-p * ";			}			#if( $icmptype ne '' ) { $cmd .= "--icmp-type $icmptype "; }			if( $sport ne '' ) { $cmd .= "--sport $sport "; }			if( $dport ne '' ) { $cmd .= "--dport $dport "; }			if( $state ne '' ) { $cmd .= "-m state --state $state "; }			if( $is_redirect ) {				if( $toport eq '' ) {					$cmd .= "-j REDIRECT";				} else {					$cmd .= "-j REDIRECT --to-port $toport";				}			} else {				# Don't redirect and return to parent chain				$cmd .= "-j RETURN";			}			if( $p ne '' ) {				$rules .= "$cmd\n";			} else {				# I must explode '-p *' in -p tcp e -p udp				$cmd =~ s/ \-p \*/ -p tcp/;				$rules .= "$cmd\n";				$cmd =~ s/ \-p tcp/ -p udp/;				$rules .= "$cmd\n";			}		}	}	return $rules;}# Applica una regola di filtro del firewallsub applyRule {	my $this = shift;	my $display = shift;	my $mangle = shift;	my %rule = @_;	if( $rule{ACTIVE} eq 'NO' ) {		return '';	}		my %fw = %{$this->{fw}};	my %fwItems = %{$this->{fwItems}};	my %services = %{$this->{services}};	my $rules = '';		my $src = $rule{SRC};	my $dst = $rule{DST};	my $target = $rule{TARGET};	my $service = $rule{SERVICE};	my $port = $rule{PORT};	my $mark = $rule{MARK};	if( $display ) {		if( $target=~ /DROP|REJECT/ ) {			print "$target $service";		} else {			print "ALLOW $service";		}		if( $service eq 'tcp' || $service eq 'udp' ) { print "($port)"; }		print " $src";		#if( $src_mac ne '' ) { print "(mac:$src_mac)"; }		print " --> $dst\n";	}	my @srcs = ();	my @src_list = split( /,/, $src );	foreach my $s (@src_list) {		if( $s eq '*' ) {			# all zones			foreach my $item ( sort(keys(%{$fw{ZONE}})) ) {				if( $item ne 'FIREWALL' ) {					push @srcs, $item;				}			}		} elsif( $fwItems{$s} eq 'GROUP' ) {			# source is a group			foreach my $item ( @{$fw{GROUP}{$s}{ITEMS}} ) {				push @srcs, $item;			}		} else {			push @srcs, $s;		}	}	# sort	@srcs = sort(@srcs);	# unique values	my $prev = '***none***';	@srcs = grep($_ ne $prev && (($prev) = $_), @srcs);	if( $#srcs > 0 ) {		# more then one element		my %newrule = %rule;		foreach my $s (@srcs) {			$newrule{SRC} = $s;			$rules .= $this->applyRule( 0, $mangle, %newrule );		}		return $rules;	} else {		$src = shift @srcs;	}	my @dsts = ();	my @dst_list = split( /,/, $dst );	foreach my $d (@dst_list) {		if( $d eq '*' ) {			# all zones			foreach my $item ( sort(keys(%{$fw{ZONE}})) ) {				if( $item ne 'FIREWALL' ) {					push @dsts, $item;				}			}		} elsif( $fwItems{$d} eq 'GROUP' ) {			# source is a group			foreach my $item ( @{$fw{GROUP}{$d}{ITEMS}} ) {				push @dsts, $item;			}		} else {			push @dsts, $d;		}	}	# sort	@dsts = sort(@dsts);	# unique values	my $prev = '***none***';	@dsts = grep($_ ne $prev && (($prev) = $_), @dsts);	if( $#dsts > 0 ) {		# more then one element		my %newrule = %rule;		foreach my $d (@dsts) {			$newrule{DST} = $d;			$rules .= $this->applyRule( 0, $mangle, %newrule );		}		return $rules;	} else {		$dst = shift @dsts;	}	# service is a list of services?	if( $service =~ /,/ ) {		my @services = split( /,/, $service );		my %newrule = %rule;		foreach my $serv (@services) {			$newrule{SERVICE} = $serv;			$rules .= $this->applyRule( 0, $mangle, %newrule );		}		return $rules;	}	my ($src_zone, $src_peer, $src_mac) = $this->expand_item( $src );	my ($dst_zone, $dst_peer) = $this->expand_item( $dst );	if( $src_zone eq 'FIREWALL' && $dst_zone eq 'FIREWALL' ) {		# ignore chain FIREWALL-FIREWALL		if( !$mangle ) {			print "** FIREWALL-->FIREWALL ignored **\n";		}		return $rules;	}	#command( "" );	#comment( "# service $service: $src --> $dst  ($src_peer -> $dst_peer) [$src_zone -> $dst_zone]" );	# Creo le 2 catene di andata e ritorno.	my $andata = "$src_zone-$dst_zone";	my $ritorno = "$dst_zone-$src_zone";		if( $mangle ) {		if( $mark ne '' ) {			$rules .= $this->applyService( \%services, $service, $andata, $ritorno, $src_peer, $src_mac, $dst_peer, $port, $target, $mark );		}	} else {		$rules .= $this->applyService( \%services, $service, $andata, $ritorno, $src_peer, $src_mac, $dst_peer, $port, $target, '' );	}		return $rules;}sub applyService {	my $this = shift;	my %calledServices = ();	return $this->_applyService( \%calledServices, @_ );}# Applica un serviziosub _applyService {	my $this = shift;	my( $ref_calledServices, $ref_services, $serviceName, $goChain, $backChain, $src, $src_mac, $dst, $port, $target, $mangle_mark ) = @_;	my %service = %{$ref_services->{$serviceName}};	my $rules = '';		$ref_calledServices->{$serviceName} = 1;	# commento del servizio	#comment( "# $serviceName: ".$service{DESCRIPTION} );	# ciclo sulle regole di filering	my $i;	for( $i = 0; $i <= $#{$service{FILTERS}}; $i++ ) {		my %filter = %{$service{FILTERS}[$i]};			if( $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) {			# It is a subservice, recursion call to _applyService			$rules .= $this->_applyService( $ref_calledServices, $ref_services, $filter{SERVICE},				$goChain, $backChain,$src, $src_mac, $dst, $port, $target, $mangle_mark );			next;		}		my $direction = $filter{DIRECTION};		my $p = $filter{P};		my $icmptype = $filter{ICMPTYPE};		my $sport = $filter{SPORT};		my $dport = $filter{DPORT};		my $state = $filter{STATE};		my $jump = $filter{JUMP};		if( $target =~ /DROP|REJECT/ && $direction ne 'go' ) {			# Don't process Back filters			next;		}		# porta impostata dalla regola del firewall		if( $sport eq 'PORT' ) {			$sport = $port;		}		if( $dport eq 'PORT' ) {			$dport = $port;		}		my $cmd;		if( $direction eq 'go' ) {			$cmd = "-A $goChain ";			if( $src ne '0.0.0.0/0' ) { $cmd .= "-s $src "; }			# MAC address			if( $src_mac =~ /^[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}$/ ) {				$cmd .= "-m mac --mac-source $src_mac ";			}			if( $dst ne '0.0.0.0/0' ) { $cmd .= "-d $dst "; }		} else {			$cmd = "-A $backChain ";			if( $dst ne '0.0.0.0/0' ) { $cmd .= "-s $dst "; }			if( $src ne '0.0.0.0/0' ) { $cmd .= "-d $src "; }		}		if( $p ne '' ) { $cmd .= "-p $p "; }		if( $icmptype ne '' ) { $cmd .= "--icmp-type $icmptype "; }		if( $sport ne '' ) { $cmd .= "--sport $sport "; }		if( $dport ne '' ) { $cmd .= "--dport $dport "; }		if( $state ne '' ) { $cmd .= "-m state --state $state "; }		# If target=DROP|REJECT then LOG before block		if( $target =~ /DROP|REJECT/ ) {			my $cmdlog = $cmd;			my $logprefix = "TFW $goChain(".substr($target,0,3).")";			if( length($logprefix) > 28 ) {				# iptables need log-prefix strings up to 29 chars length				$logprefix = substr( $logprefix, 0, 28 );			}			$cmdlog .= "-m limit --limit $this->{log_limit}/hour --limit-burst $this->{log_limit_burst} -j LOG --log-prefix \"$logprefix:\"";			$rules .= "$cmdlog\n";			$jump = $target;		}		# Se e' in andata accetto il passaggio del pacchetto se e' in ritorno lo invio		# alla catena BACK che si occupa di verificare che sia realmente un pacchetto di		# una connessione gia' aperta.		if( $mangle_mark eq '' ) {			# filter rule			if( $jump eq '' ) {				$cmd .= "-j ".( $direction eq 'go' ? 'ACCEPT' : 'BACK' );			} else {				$cmd .= "-j $jump";			}		} else {			# mangle rule			if( $jump eq '' ) {				if( $direction ne 'go' && $state eq '' ) {					# BACK					$cmd .= "-m state --state ESTABLISHED,RELATED ";				} 				$cmd .= "-j MARK --set-mark $mangle_mark";			} else {				if( $jump eq 'ICMP-ACC' ) {					# ICMP-ACC					my $prot = $p eq 'icmp' ? '' : '-p icmp'; 					$cmd = "$cmd $prot --icmp-type destination-unreachable -j MARK --set-mark $mangle_mark\n".						"$cmd $prot --icmp-type source-quench -j MARK --set-mark $mangle_mark\n".						"$cmd $prot --icmp-type time-exceeded -j MARK --set-mark $mangle_mark\n".						"$cmd $prot --icmp-type parameter-problem -j MARK --set-mark $mangle_mark";				} else {					$cmd .= "-j MARK --set-mark $mangle_mark";				}			}		}				#print "\n$cmd\n";		$rules .= "$cmd\n";	}	return $rules;}# dato il nome dell'item ritorna la zona e l'ip + netmasksub expand_item {	my $this = shift;	my $item = shift;		my %fw = %{$this->{fw}};	my %fwItems = %{$this->{fwItems}};	my $itemType = $fwItems{$item};	my $zone = '';	my $ip = '';	my $mac = '';	if( $itemType eq 'ZONE' ) {		$zone = $item;		$ip = '0.0.0.0/0';	}	if( $itemType eq 'NET' ) {		$zone = $fw{NET}{$item}{ZONE};		$ip = $fw{NET}{$item}{IP}.'/'.$fw{NET}{$item}{NETMASK};	}	if( $itemType eq 'HOST' ) {		$zone = $fw{HOST}{$item}{ZONE};		$ip = $fw{HOST}{$item}{IP}.'/32';		$mac = $fw{HOST}{$item}{MAC};	}	return ($zone, $ip, $mac);}sub command {	my $this = shift;	my $cmd = shift;	my $out = qx{$cmd 2>&1};	if( $out ne '' ) {		print "$cmd\n$out";	}}sub iptables_restore_emu {	my $this = shift;	my $rules = shift;		my $table = '';	my @lines = split(/\n/, $rules);	foreach my $line (@lines) {		$line =~ s/\#(.*)$//;		if( !$line || $line eq 'COMMIT' ) {			next;		}		if( $line =~ /^\*(.*?)$/ ) {			$table = $1 eq 'filter' ? '' : $1;			next;		}		my $cmd = '';		my $chain = '';		my $policy = '';		if( $line =~ /^\:(.*?) (.*?) (.*?)$/ ) {			$chain = $1;			$policy = $2;			if( $chain =~ /^(INPUT|OUTPUT|FORWARD)$/ ) {				next;			}			$cmd = "-N $chain". ($policy ne '-' ? " -P $policy" : ''); 		} else {			$cmd = $line;		}		if( $table ) { $cmd = "-t $table $cmd"; }				$this->command("iptables $cmd");	}}1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -