diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index d9834ed00..3a221a6c1 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -2637,9 +2637,12 @@ sub initialize_chain_table($) { # As new targets (Actions, Macros and Manual Chains) are discovered, they are added to the table # %targets = ('ACCEPT' => STANDARD, + 'ACCEPT+' => STANDARD + NONAT, 'ACCEPT!' => STANDARD, + 'A_ACCEPT+' => STANDARD + NONAT + AUDIT, 'AUDIT' => STANDARD + AUDIT, 'A_ACCEPT' => STANDARD + AUDIT, + 'NONAT' => STANDARD + NONAT + NATONLY, 'DROP' => STANDARD, 'DROP!' => STANDARD, 'A_DROP' => STANDARD + AUDIT, @@ -2648,6 +2651,10 @@ sub initialize_chain_table($) { 'REJECT!' => STANDARD, 'A_REJECT' => STANDARD + AUDIT, 'A_REJECT!' => STANDARD + AUDIT, + 'DNAT' => NATRULE, + 'DNAT-' => NATRULE + NATONLY, + 'REDIRECT' => NATRULE + REDIRECT, + 'REDIRECT-' => NATRULE + REDIRECT + NATONLY, 'LOG' => STANDARD + LOGRULE, 'CONTINUE' => STANDARD, 'CONTINUE!' => STANDARD, diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 8a936294a..89c2d8341 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -807,7 +807,7 @@ sub compiler { # # Setup Nat # - setup_nat; + setup_nat if $family == F_IPV4; # # Setup NETMAP # diff --git a/Shorewall/Perl/Shorewall/Nat.pm b/Shorewall/Perl/Shorewall/Nat.pm index a9d4b590e..4e4a80af2 100644 --- a/Shorewall/Perl/Shorewall/Nat.pm +++ b/Shorewall/Perl/Shorewall/Nat.pm @@ -44,11 +44,13 @@ our $VERSION = 'MODULEVERSION'; our @addresses_to_add; our %addresses_to_add; +our $family; # # Called by the compiler # -sub initialize() { +sub initialize($) { + $family = shift; @addresses_to_add = (); %addresses_to_add = (); } @@ -61,7 +63,7 @@ sub process_one_masq1( $$$$$$$$$$ ) my ($interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest ) = @_; my $pre_nat; - my $add_snat_aliases = $config{ADD_SNAT_ALIASES}; + my $add_snat_aliases = $family == F_IPV4 && $config{ADD_SNAT_ALIASES}; my $destnets = ''; my $baserule = ''; @@ -72,28 +74,30 @@ sub process_one_masq1( $$$$$$$$$$ ) # # Parse the remaining part of the INTERFACE column # - if ( $interfacelist =~ /^([^:]+)::([^:]*)$/ ) { - $add_snat_aliases = 0; - $destnets = $2; - $interfacelist = $1; - } elsif ( $interfacelist =~ /^([^:]+:[^:]+):([^:]+)$/ ) { - $destnets = $2; - $interfacelist = $1; - } elsif ( $interfacelist =~ /^([^:]+):$/ ) { - $add_snat_aliases = 0; - $interfacelist = $1; - } elsif ( $interfacelist =~ /^([^:]+):([^:]*)$/ ) { - my ( $one, $two ) = ( $1, $2 ); - if ( $2 =~ /\./ || $2 =~ /^%/ ) { - $interfacelist = $one; - $destnets = $two; + if ( $family == F_IPV4 ) { + if ( $interfacelist =~ /^([^:]+)::([^:]*)$/ ) { + $add_snat_aliases = 0; + $destnets = $2; + $interfacelist = $1; + } elsif ( $interfacelist =~ /^([^:]+:[^:]+):([^:]+)$/ ) { + $destnets = $2; + $interfacelist = $1; + } elsif ( $interfacelist =~ /^([^:]+):$/ ) { + $add_snat_aliases = 0; + $interfacelist = $1; + } elsif ( $interfacelist =~ /^([^:]+):([^:]*)$/ ) { + my ( $one, $two ) = ( $1, $2 ); + if ( $2 =~ /\./ || $2 =~ /^%/ ) { + $interfacelist = $one; + $destnets = $two; + } } } # # If there is no source or destination then allow all addresses # - $networks = ALLIPv4 if $networks eq '-'; - $destnets = ALLIPv4 if $destnets eq '-'; + $networks = ALLIP if $networks eq '-'; + $destnets = ALLIP if $destnets eq '-'; # # Handle IPSEC options, if any @@ -162,6 +166,7 @@ sub process_one_masq1( $$$$$$$$$$ ) # if ( $addresses ne '-' ) { if ( $addresses eq 'random' ) { + fatal_error 'Invalid IPv6 address (random)' if $family == F_IPV6; $randomize = '--random '; } else { $addresses =~ s/:persistent$// and $persistent = ' --persistent '; @@ -187,7 +192,9 @@ sub process_one_masq1( $$$$$$$$$$ ) $add_snat_aliases = 0; } else { my $addrlist = ''; - for my $addr ( split_list $addresses , 'address' ) { + my @addrs = split_list $addresses, 'address'; + + for my $addr ( @addrs ) { if ( $addr =~ /^([&%])(.+)$/ ) { my ( $type, $interface ) = ( $1, $2 ); $target = 'SNAT '; @@ -199,22 +206,57 @@ sub process_one_masq1( $$$$$$$$$$ ) } else { $addrlist .= '--to-source ' . record_runtime_address( $type, $interface ); } - } elsif ( $addr =~ /^.*\..*\..*\./ ) { - $target = 'SNAT '; - my ($ipaddr, $rest) = split ':', $addr; - if ( $ipaddr =~ /^(.+)-(.+)$/ ) { - validate_range( $1, $2 ); + } elsif ( $family == F_IPV4 ) { + if ( $addr =~ /^.*\..*\..*\./ ) { + $target = 'SNAT '; + my ($ipaddr, $rest) = split ':', $addr; + if ( $ipaddr =~ /^(.+)-(.+)$/ ) { + validate_range( $1, $2 ); + } else { + validate_address $ipaddr, 0; + } + $addrlist .= "--to-source $addr "; + $exceptionrule = do_proto( $proto, '', '' ) if $addr =~ /:/; } else { - validate_address $ipaddr, 0; + my $ports = $addr; + $ports =~ s/^://; + validate_portpair1( $proto, $ports ); + $addrlist .= "--to-ports $ports "; + $exceptionrule = do_proto( $proto, '', '' ); } - $addrlist .= "--to-source $addr "; - $exceptionrule = do_proto( $proto, '', '' ) if $addr =~ /:/; } else { - my $ports = $addr; - $ports =~ s/^://; - validate_portpair1( $proto, $ports ); - $addrlist .= "--to-ports $ports "; - $exceptionrule = do_proto( $proto, '', '' ); + fatal_error "Only one IPv6 ADDRESS may be specified" if @addrs > 1; + + $target = 'SNAT '; + + if ( $addr =~ /^\[/ ) { + # + # Can have ports specified + # + my $ports; + + if ( $addr =~ s/:([^]]+)$// ) { + $ports = $1; + } + + fatal_error "Invalid IPv6 Address ($addr)" unless $addr =~ /^\[(.+)\]$/; + + $addr = $1; + + if ( $addr =~ /^(.+)-(.+)$/ ) { + validate_range( $1, $2 ); + } else { + validate_address $addr, 0; + } + + $addrlist .= "--to-source $addr "; + + if ( supplied $ports ) { + validate_portpair( $proto, $ports ); + $exceptionrule = do_proto( $proto, '', '' ); + $addrlist .= "--toports $ports "; + } + } } } @@ -225,6 +267,7 @@ sub process_one_masq1( $$$$$$$$$$ ) $target .= $randomize; $target .= $persistent; } else { + fatal_error "IPv6 does does not support MASQUERADE -- you must use SNAT" if $family == F_IPV6; $add_snat_aliases = 0; } # @@ -597,9 +640,18 @@ sub handle_nat_rule( $$$$$$$$$$$$ ) { if ( $server eq '' ) { fatal_error "A server and/or port must be specified in the DEST column in $action rules" unless $serverport; } elsif ( $server =~ /^(.+)-(.+)$/ ) { - validate_range( $1, $2 ); + if ( $family == F_IPV4 ) { + validate_range( $1, $2 ); + } else { + my ( $addr1, $addr2 ) = ( $1, $2 ); + $addr1 = $1 if $addr1 =~ /^\[(.+)\]$/; + $addr2 = $1 if $addr2 =~ /^\[(.+)\]$/; + validate_range( $addr1, $addr2 ); + $server = join '-', $addr1, $addr2 + } } else { unless ( $server eq ALLIP ) { + $server = $1 if $family == F_IPV6 && $server =~ /^\[(.+)\]$/; my @servers = validate_address $server, 1; $server = join ',', @servers; } @@ -609,8 +661,15 @@ sub handle_nat_rule( $$$$$$$$$$$$ ) { $target = $action; if ( $server ) { $serverport = ":$serverport" if $serverport; - for my $serv ( split /,/, $server ) { - $target .= " --to-destination ${serv}${serverport}"; + if ( $family == F_IPV4 ) { + for my $serv ( split /,/, $server ) { + $target .= " --to-destination ${serv}${serverport}"; + } + } else { + for my $serv ( split /,/, $server ) { + $serv =~ s/-/]-[/; #In case this is a range. + $target .= " --to-destination [${serv}]${serverport}"; + } } } else { $target .= " --to-destination :$serverport"; diff --git a/Shorewall6/configfiles/masq b/Shorewall6/configfiles/masq new file mode 100644 index 000000000..c8b582bb6 --- /dev/null +++ b/Shorewall6/configfiles/masq @@ -0,0 +1,11 @@ +# +# Shorewall6 version 4 - Masq file +# +# For information about entries in this file, type "man shorewall6-masq" +# +# The manpage is also online at +# http://www.shorewall.net/manpages6/shorewall6-masq.html +# +######################################################################################################################## +#INTERFACE SOURCE ADDRESS PROTO PORT(S) IPSEC MARK USER/ SWITCH ORIGINAL +# GROUP DEST diff --git a/Shorewall6/manpages/shorewall6-masq.xml b/Shorewall6/manpages/shorewall6-masq.xml new file mode 100644 index 000000000..1c6fc5830 --- /dev/null +++ b/Shorewall6/manpages/shorewall6-masq.xml @@ -0,0 +1,533 @@ + + + + + shorewall6-masq + + 5 + + + + masq + + Shorewall6 SNAT definition file + + + + + /etc/shorewall/masq + + + + + Description + + Use this file to define Source NAT (SNAT). + + + Unlike with IPv4, Netfilter does not support the MASQUERADE target + with IPv6. + + + + The entries in this file are order-sensitive. The first entry that + matches a particular connection will be the one that is used. + + + + If you have more than one ISP link, adding entries to this file + will not force connections to go out + through a particular link. You must use entries in shorewall6-rtrules(5) or + PREROUTING entries in shorewall-tcrules(5) to do + that. + + + The columns in the file are as follows. + + + + INTERFACE:DEST - {[+]interfacelist|[?]COMMENT} + + + Outgoing interfacelist. This may be a + comma-separated list of interface names. This is usually your + internet interface. + + Each interface must match an entry in shorewall6-interfaces(5). + Shorewall allows loose matches to wildcard entries in shorewall6-interfaces(5). + For example, ppp0 in this + file will match a shorewall6-interfaces(5) + entry that defines ppp+. + + Where more that + one internet provider share a single interface, the provider + is specified by including the provider name or number in + parentheses: + + eth0(Avvanta) + + In that case, you will want to specify the interfaces's + address for that provider in the ADDRESS column. + + The interface may be qualified by adding the character ":" + followed by a comma-separated list of destination host or subnet + addresses to indicate that you only want to change the source IP + address for packets being sent to those particular destinations. + Exclusion is allowed (see shorewall-exclusion(5)) as + are ipset names preceded by a plus sign '+'; + + If you wish to inhibit the action of ADD_SNAT_ALIASES for this + entry then include the ":" but omit the digit: + + eth0(Avvanta): + eth2::192.0.2.32/27 + + Normally Masq/SNAT rules are evaluated after those for + one-to-one NAT (defined in shorewall-nat(5)). If you want the + rule to be applied before one-to-one NAT rules, prefix the interface + name with "+": + + +eth0 + +eth0:192.0.2.32/27 + +eth0:2 + + This feature should only be required if you need to insert + rules in this file that preempt entries in shorewall-nat(5). + + Comments may be attached to Netfilter rules generated from + entries in this file through the use of COMMENT lines. These lines + begin with the word COMMENT; the remainder of the line is treated as + a comment which is attached to subsequent rules until another + COMMENT line is found or until the end of the file is reached. To + stop adding comments to rules, use a line with only the word + COMMENT. + + + Beginning with Shorewall 4.5.11, ?COMMENT is a synonym for + COMMENT and is preferred. + + + + + + SOURCE - + {interface|address[,address][exclusion]} + + + Set of hosts that you wish to SNAT; one or more host or + network addresses separated by comma. You may use ipset names + preceded by a plus sign (+) to specify a set of hosts. + + + + + ADDRESS - + {address-or-address-range[,address-or-address-range]...][:lowport-highport][:random][:persistent]|} + + + The address specified here will be used as the source address. + If you simply wish to use the IPv6 address of the + interface in the first column, enter the + name of that interface preceded by an apersand ('&') - e.g., + &sit1. + + You may also specify a range of up to 256 IP addresses if you + want the SNAT address to be assigned from that range in a + round-robin fashion by connection. The range is specified by + first.ip.in.range-last.ip.in.range. + The address or address range may be optionally followed by a port + range. When this is done, you must enclose the IPv6 address(es) in + square brackets. You may follow the port range with :random in which case assignment of ports + from the range will be random. + + Example: + [2001:470:a:227::2]-[2001:470:a:227::10]::1000-1010 + + You may follow the port range (or :random) with :persistent. This is only useful when an + address range is specified and causes a client to be given the same + source/destination IP pair. + + Finally, you may also specify a comma-separated list of ranges + and/or addresses in this column. + + This column may not contain DNS Names. + + Normally, Netfilter will attempt to retain the source port + number. You may cause netfilter to remap the source port by + following an address or range (if any) by ":" and a port range with + the format + lowport-highport. If this + is done, you must specify "tcp" or "udp" in the PROTO column. + + Examples: + + [2001:470:a:787::2]:5000-6000 + + If you simply place NONAT in + this column, no rewriting of the source IP address or port number + will be performed. This is useful if you want particular traffic to + be exempt from the entries that follow in the file. + + + + + PROTO (Optional) - {-|[!]{protocol-name|protocol-number}[,...]} + + + If you wish to restrict this entry to a particular protocol + then enter the protocol name (from protocols(5)) or number + here. + + Beginning with Shorewall 4.5.12, this column can accept a + comma-separated list of protocols. + + + + + PORT(S) (Optional) - + [[!]port-name-or-number[,port-name-or-number]...] + + + If the PROTO column specifies TCP (6), UDP (17), DCCP (33), + SCTP (132) or UDPLITE (136) then you may list one or more port + numbers (or names from services(5)) or port ranges separated by + commas. + + Port ranges are of the form + lowport:highport. + + + + + IPSEC (Optional) - + [option[,option]...] + + + If you specify a value other than "-" in this column, you must + be running kernel 2.6 and your kernel and iptables must include + policy match support. + + Comma-separated list of options from the following. Only + packets that will be encrypted via an SA that matches these options + will have their source address changed. + + + + reqid=number + + + where number is specified using + setkey(8) using the 'unique:number option + for the SPD level. + + + + + spi=<number> + + + where number is the SPI of the SA + used to encrypt/decrypt packets. + + + + + proto=ah|esp|ipcomp + + + IPSEC Encapsulation Protocol + + + + + mss=number + + + sets the MSS field in TCP packets + + + + + mode=transport|tunnel + + + IPSEC mode + + + + + tunnel-src=address[/mask] + + + only available with mode=tunnel + + + + + tunnel-dst=address[/mask] + + + only available with mode=tunnel + + + + + strict + + + Means that packets must match all rules. + + + + + next + + + Separates rules; can only be used with strict + + + + + yes + + + When used by itself, causes all traffic that will be + encrypted/encapsulated to match the rule. + + + + + + + + MARK - [!]value[/mask][:C] + + + Defines a test on the existing packet or connection mark. The + rule will match only if the test returns true. + + If you don't want to define a test but need to specify + anything in the following columns, place a "-" in this field. + + + + ! + + + Inverts the test (not equal) + + + + + value + + + Value of the packet or connection mark. + + + + + mask + + + A mask to be applied to the mark before testing. + + + + + :C + + + Designates a connection mark. If omitted, the packet + mark's value is tested. + + + + + + + + USER/GROUP (Optional) - + [!][user-name-or-number][:group-name-or-number][+program-name] + + + Only locally-generated connections will match if this column + is non-empty. + + When this column is non-empty, the rule matches only if the + program generating the output is running under the effective + user and/or group + specified (or is NOT running under that id if "!" is given). + + Examples: + + + + joe + + + program must be run by joe + + + + + :kids + + + program must be run by a member of the 'kids' + group + + + + + !:kids + + + program must not be run by a member of the 'kids' + group + + + + + +upnpd + + + #program named upnpd + + + The ability to specify a program name was removed from + Netfilter in kernel version 2.6.14. + + + + + + + + + SWITCH - + [!]switch-name[={0|1}] + + + Added in Shorewall 4.5.1 and allows enabling and disabling the + rule without requiring shorewall restart. + + The rule is enabled if the value stored in + /proc/net/nf_condition/switch-name + is 1. The rule is disabled if that file contains 0 (the default). If + '!' is supplied, the test is inverted such that the rule is enabled + if the file contains 0. + + Within the switch-name, '@0' and + '@{0}' are replaced by the name of the chain to which the rule is a + added. The switch-name (after '@...' + expansion) must begin with a letter and be composed of letters, + decimal digits, underscores or hyphens. Switch names must be 30 + characters or less in length. + + Switches are normally off. To + turn a switch on: + + + echo 1 > + /proc/net/nf_condition/switch-name + + + To turn it off again: + + + echo 0 > + /proc/net/nf_condition/switch-name + + + Switch settings are retained over shorewall + restart. + + Beginning with Shoreawll 4.5.10, when the + switch-name is followed by + or , then the switch is + initialized to off or on respectively by the + start command. Other commands do not affect the + switch setting. + + + + + ORIGINAL DEST (origdest) - + [-|address[,address]...[exclusion]|exclusion] + + + (Optional) Added in Shorewall 4.5.6. This column may be + included and may contain one or more addresses (host or network) + separated by commas. Address ranges are not allowed. When this + column is supplied, rules are generated that require that the + original destination address matches one of the listed addresses. It + is useful for specifying that SNAT should occur only for connections + that were acted on by a DNAT when they entered the firewall. + + + + + + + Examples + + + + Example 1: + + + You have a simple 'masquerading' setup where eth0 connects to + a DSL or cable modem and eth1 connects to your local network with + subnet 2001:470:b:787::0/64 + + Your entry in the file will be: + + #INTERFACE SOURCE ADDRESS + eth0 2001:470:b:787::0/64 &eth0 + + + + + + + FILES + + /etc/shorewall6/masq + + diff --git a/Shorewall6/manpages/shorewall6-rules.xml b/Shorewall6/manpages/shorewall6-rules.xml index 5c88f0787..92cc36710 100644 --- a/Shorewall6/manpages/shorewall6-rules.xml +++ b/Shorewall6/manpages/shorewall6-rules.xml @@ -173,6 +173,19 @@ + + ACCEPT+ + + + like ACCEPT but also excludes the connection from any + subsequent matching DNAT[-] or REDIRECT[-] rules. + + + ACCEPT! @@ -333,6 +346,28 @@ + + DNAT + + + Forward the request to another system (and optionally + another port). + + + + + DNAT- + + + Advanced users only. + + Like DNAT but only + generates the DNAT iptables + rule and not the companion ACCEPT rule. + + + DROP @@ -470,6 +505,28 @@ + + REDIRECT + + + Redirect the request to a server running on the + firewall. + + + + + REDIRECT- + + + Advanced users only. + + Like REDIRECT but only + generates the REDIRECT + iptables rule and not the companion ACCEPT rule. + + + REJECT