From caa4a54e388ac3b2d816c6025cee8e3d59aeb060 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Fri, 10 Dec 2010 19:06:44 -0800 Subject: [PATCH] Implement IPv6 proxyndp --- Shorewall/Perl/Shorewall/Compiler.pm | 13 ++- Shorewall/Perl/Shorewall/Proxyarp.pm | 126 ++++++++++++--------------- Shorewall/Perl/Shorewall/Rules.pm | 19 +++- Shorewall/Perl/prog.header | 6 +- Shorewall/Perl/prog.header6 | 16 ++++ 5 files changed, 102 insertions(+), 78 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 635ad31ec..ef97cc48e 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -388,7 +388,11 @@ sub generate_script_3($) { '' ); save_dynamic_chains; mark_firewall_not_started; - emit ''; + + emit ('', + 'delete_proxyndp', + '' + ); } emit qq(delete_tc1\n) if $config{CLEAR_TC}; @@ -397,7 +401,12 @@ sub generate_script_3($) { emit( 'setup_routing_and_traffic_shaping', '' ); - emit 'cat > ${VARDIR}/proxyarp << __EOF__'; + if ( $family == F_IPV4 ) { + emit 'cat > ${VARDIR}/proxyarp << __EOF__'; + } else { + emit 'cat > ${VARDIR}/proxyndp << __EOF__'; + } + dump_proxy_arp; emit_unindented '__EOF__'; diff --git a/Shorewall/Perl/Shorewall/Proxyarp.pm b/Shorewall/Perl/Shorewall/Proxyarp.pm index 9aa9b32fb..0d8eab59f 100644 --- a/Shorewall/Perl/Shorewall/Proxyarp.pm +++ b/Shorewall/Perl/Shorewall/Proxyarp.pm @@ -59,6 +59,8 @@ sub initialize( $ ) { sub setup_one_proxy_arp( $$$$$$$ ) { my ( $address, $interface, $physical, $external, $extphy, $haveroute, $persistent) = @_; + my $proto = $family == F_IPV4 ? 'ARP' : 'NDP'; + if ( "\L$haveroute" eq 'no' || $haveroute eq '-' ) { $haveroute = ''; } elsif ( "\L$haveroute" eq 'yes' ) { @@ -76,107 +78,91 @@ sub setup_one_proxy_arp( $$$$$$$ ) { } unless ( $haveroute ) { - emit "[ -n \"\$g_noroutes\" ] || run_ip route replace $address dev $physical"; + if ( $family == F_IPV4 ) { + emit "[ -n \"\$g_noroutes\" ] || run_ip route replace $address/32 dev $physical"; + } else { + emit "[ -n \"\$g_noroutes\" ] || run_ip route replace $address/128 dev $physical"; + } + $haveroute = 1 if $persistent; } - emit ( "if ! arp -i $extphy -Ds $address $extphy pub; then", - " fatal_error \"Command 'arp -i $extphy -Ds $address $extphy pub' failed\"" , - 'fi' , - '', - "progress_message \" Host $address connected to $interface added to ARP on $extphy\"\n" ); + emit ( "run_ip neigh add proxy $address nud permanent dev $extphy" , + qq(progress_message " Host $address connected to $interface added to $proto on $extphy"\n) ); push @proxyarp, "$address $interface $external $haveroute"; - progress_message " Host $address connected to $interface added to ARP on $external"; + progress_message " Host $address connected to $interface added to $proto on $external"; } # -# Setup Proxy ARP +# Setup Proxy ARP/NDP # sub setup_proxy_arp() { - if ( $family == F_IPV4 ) { + my $proto = $family == F_IPV4 ? 'arp' : 'ndp'; # Protocol + my $file_opt = 'proxy' . $proto; # Name of config file and of the interface option + my $proc_file = 'proxy_' . $proto; # Name of the corresponding file in /proc - my $interfaces= find_interfaces_by_option 'proxyarp'; - my $fn = open_file 'proxyarp'; + my $interfaces= find_interfaces_by_option $file_opt; + my $fn = open_file $file_opt; - if ( @$interfaces || $fn ) { + if ( @$interfaces || $fn ) { - my $first_entry = 1; + my $first_entry = 1; - save_progress_message "Setting up Proxy ARP..."; + save_progress_message 'Setting up Proxy ' . uc($proto) . '...'; - my ( %set, %reset ); + my ( %set, %reset ); - while ( read_a_line ) { + while ( read_a_line ) { - my ( $address, $interface, $external, $haveroute, $persistent ) = split_line 3, 5, 'proxyarp file'; + my ( $address, $interface, $external, $haveroute, $persistent ) = split_line 3, 5, 'proxyarp file'; - if ( $first_entry ) { - progress_message2 "$doing $fn..."; - $first_entry = 0; - } - - my $physical = physical_name $interface; - my $extphy = physical_name $external; - - $set{$interface} = 1; - $reset{$external} = 1 unless $set{$external}; - - setup_one_proxy_arp( $address, $interface, $physical, $external, $extphy, $haveroute, $persistent ); + if ( $first_entry ) { + progress_message2 "$doing $fn..."; + $first_entry = 0; } - emit ''; + my $physical = physical_name $interface; + my $extphy = physical_name $external; - for my $interface ( keys %reset ) { - unless ( $set{interface} ) { - my $physical = get_physical $interface; - emit ( "if [ -f /proc/sys/net/ipv4/conf/$physical/proxy_arp ]; then" , - " echo 0 > /proc/sys/net/ipv4/conf/$physical/proxy_arp" ); - emit "fi\n"; - } - } + $set{$interface} = 1; + $reset{$external} = 1 unless $set{$external}; - for my $interface ( keys %set ) { + setup_one_proxy_arp( $address, $interface, $physical, $external, $extphy, $haveroute, $persistent ); + } + + emit ''; + + for my $interface ( keys %reset ) { + unless ( $set{interface} ) { my $physical = get_physical $interface; - emit ( "if [ -f /proc/sys/net/ipv4/conf/$physical/proxy_arp ]; then" , - " echo 1 > /proc/sys/net/ipv4/conf/$physical/proxy_arp" ); - emit ( 'else' , - " error_message \" WARNING: Cannot set the 'proxy_arp' option for interface $physical\"" ) unless interface_is_optional( $interface ); + emit ( "if [ -f /proc/sys/net/ipv$family/conf/$physical/$proc_file ]; then" , + " echo 0 > /proc/sys/net/ipv$family/conf/$physical/$proc_file" ); emit "fi\n"; } - - for my $interface ( @$interfaces ) { - my $value = get_interface_option $interface, 'proxyarp'; - my $optional = interface_is_optional $interface; - - $interface = get_physical $interface; - - emit ( "if [ -f /proc/sys/net/ipv4/conf/$interface/proxy_arp ] ; then" , - " echo $value > /proc/sys/net/ipv4/conf/$interface/proxy_arp" ); - emit ( 'else' , - " error_message \"WARNING: Unable to set/reset proxy ARP on $interface\"" ) unless $optional; - emit "fi\n"; - } } - } else { - my $interfaces= find_interfaces_by_option 'proxyndp'; - if ( @$interfaces ) { - save_progress_message "Setting up Proxy NDP..."; + for my $interface ( keys %set ) { + my $physical = get_physical $interface; + emit ( "if [ -f /proc/sys/net/ipv$family/conf/$physical/$proc_file ]; then" , + " echo 1 > /proc/sys/net/ipv$family/conf/$physical/$proc_file" ); + emit ( 'else' , + " error_message \" WARNING: Cannot set the '$file_opt' option for interface $physical\"" ) unless interface_is_optional( $interface ); + emit "fi\n"; + } - for my $interface ( @$interfaces ) { - my $value = get_interface_option $interface, 'proxyndp'; - my $optional = interface_is_optional $interface; + for my $interface ( @$interfaces ) { + my $value = get_interface_option $interface, $file_opt; + my $optional = interface_is_optional $interface; - $interface = get_physical $interface; + $interface = get_physical $interface; - emit ( "if [ -f /proc/sys/net/ipv6/conf/$interface/proxy_ndp ] ; then" , - " echo $value > /proc/sys/net/ipv6/conf/$interface/proxy_ndp" ); - emit ( 'else' , - " error_message \"WARNING: Unable to set/reset Proxy NDP on $interface\"" ) unless $optional; - emit "fi\n"; - } + emit ( "if [ -f /proc/sys/net/ipv$family/conf/$interface/$proc_file ] ; then" , + " echo $value > /proc/sys/net/ipv$family/conf/$interface/$proc_file" ); + emit ( 'else' , + " error_message \"WARNING: Unable to set/reset the '$file_opt' option on $interface\"" ) unless $optional; + emit "fi\n"; } } } diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index f72136753..ad7f6209a 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -2520,8 +2520,8 @@ EOF emit <<'EOF'; if [ -f ${VARDIR}/proxyarp ]; then while read address interface external haveroute; do - qt arp -i $external -d $address pub - [ -z "${haveroute}${g_noroutes}" ] && qt $IP -4 route del $address dev $interface + qt $IP -4 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qt $IP -4 route del $address/32 dev $interface f=/proc/sys/net/ipv4/conf/$interface/proxy_arp [ -f $f ] && echo 0 > $f done < ${VARDIR}/proxyarp @@ -2530,7 +2530,20 @@ EOF fi EOF - } + } else { + emit <<'EOF'; + if [ -f ${VARDIR}/proxyndp ]; then + while read address interface external haveroute; do + qt $IP -6 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qt $IP -6 route del $address/128 dev $interface + f=/proc/sys/net/ipv4/conf/$interface/proxy_ndp + [ -f $f ] && echo 0 > $f + done < ${VARDIR}/proxyndp + + rm -f ${VARDIR}/proxyndp + fi + +EOF push_indent; diff --git a/Shorewall/Perl/prog.header b/Shorewall/Perl/prog.header index f7908fdda..1b8f91a1c 100644 --- a/Shorewall/Perl/prog.header +++ b/Shorewall/Perl/prog.header @@ -593,8 +593,8 @@ conditionally_flush_conntrack() { delete_proxyarp() { if [ -f ${VARDIR}/proxyarp ]; then while read address interface external haveroute; do - qt arp -i $external -d $address pub - [ -z "${haveroute}${g_noroutes}" ] && qt $IP -4 route del $address dev $interface + qt $IP -4 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qt $IP -4 route del $address/32 dev $interface f=/proc/sys/net/ipv4/conf/$interface/proxy_arp [ -f $f ] && echo 0 > $f done < ${VARDIR}/proxyarp @@ -603,7 +603,7 @@ delete_proxyarp() { fi } -# +\# # Remove all Shorewall-added rules # clear_firewall() { diff --git a/Shorewall/Perl/prog.header6 b/Shorewall/Perl/prog.header6 index 774023dc6..588fd89b8 100644 --- a/Shorewall/Perl/prog.header6 +++ b/Shorewall/Perl/prog.header6 @@ -573,6 +573,22 @@ conditionally_flush_conntrack() { fi } +# +# Clear Proxy NDP +# +delete_proxyndp() { + if [ -f ${VARDIR}/proxyndp ]; then + while read address interface external haveroute; do + qt $IP -6 neigh del proxy $address dev $external + [ -z "${haveroute}${g_noroutes}" ] && qt $IP -6 route del $address/128 dev $interface + f=/proc/sys/net/ipv6/conf/$interface/proxy_ndp + [ -f $f ] && echo 0 > $f + done < ${VARDIR}/proxyndp + + rm -f ${VARDIR}/proxyndp + fi +} + # # Remove all Shorewall-added rules #