Skip to content

Commit

Permalink
Add IPv6 support for forward-ports in zones
Browse files Browse the repository at this point in the history
The loader, the zone handler, the documentation and also firewall-config have
been adapted for this.

New tests for firewall-cmd and firewall-offline-cmd have been added.

Depends on c647531:
firewall.command: Enable parse_forward_port to work with IPv6 adresses
  • Loading branch information
t-woerner committed Jun 7, 2017
1 parent c647531 commit a62db0f
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 20 deletions.
6 changes: 3 additions & 3 deletions doc/xml/firewalld.zone.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
[ &lt;icmp-block name="<replaceable>string</replaceable>"/&gt; ]
[ &lt;icmp-block-inversion/&gt; ]
[ &lt;masquerade/&gt; ]
[ &lt;forward-port port="<replaceable>portid</replaceable>[-<replaceable>portid</replaceable>]" protocol="<literal>tcp</literal>|<literal>udp</literal>|<literal>sctp</literal>|<literal>dccp</literal>" [to-port="<replaceable>portid</replaceable>[-<replaceable>portid</replaceable>]"] [to-addr="<replaceable>ipv4address</replaceable>"]/&gt; ]
[ &lt;forward-port port="<replaceable>portid</replaceable>[-<replaceable>portid</replaceable>]" protocol="<literal>tcp</literal>|<literal>udp</literal>|<literal>sctp</literal>|<literal>dccp</literal>" [to-port="<replaceable>portid</replaceable>[-<replaceable>portid</replaceable>]"] [to-addr="<replaceable>IP address</replaceable>"]/&gt; ]
[ &lt;source-port port="<replaceable>portid</replaceable>[-<replaceable>portid</replaceable>]" protocol="<literal>tcp</literal>|<literal>udp</literal>|<literal>sctp</literal>|<literal>dccp</literal>"/&gt; ]
[
&lt;rule [family="<literal>ipv4</literal>|<literal>ipv6</literal>"]&gt;
Expand Down Expand Up @@ -310,7 +310,7 @@
<refsect2 id="forward-port">
<title>forward-port</title>
<para>
Is an optional empty-element tag and can be used several times to have more than one port or packet forward entry. This is for IPv4 only. Use rich language rules for IPv6. There are mandatory and also optional attributes for forward ports:
Is an optional empty-element tag and can be used several times to have more than one port or packet forward entry. There are mandatory and also optional attributes for forward ports:
</para>

<refsect3>
Expand Down Expand Up @@ -358,7 +358,7 @@
<term>to-addr="<replaceable>address</replaceable>"</term>
<listitem>
<para>
The destination IPv4 IP address.
The destination IP address either for IPv4 or IPv6.
</para>
</listitem>
</varlistentry>
Expand Down
2 changes: 1 addition & 1 deletion src/firewall-config
Original file line number Diff line number Diff line change
Expand Up @@ -4970,7 +4970,7 @@ class FirewallConfig(object):
self.forwardDialogLocalCheck.set_active(True)
self.forwardDialogLocalCheck.set_active(False)
self.forwardDialogToPortCheck.set_active(False)
self.forwardDialog.family = "ipv4"
self.forwardDialog.family = None

old_port = None
old_proto = None
Expand Down
34 changes: 23 additions & 11 deletions src/firewall/core/fw_zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ def __rule_prepare(self, enable, zone, rule, mark_id, zone_transaction):
self.check_forward_port(ipv, port, protocol, toport, toaddr)

if enable:
enable_ip_forwarding(ipv)
zone_transaction.add_post(enable_ip_forwarding, ipv)
mark_id = self._fw.new_mark()

filter_chain = "INPUT" if not toaddr else "FORWARD_IN"
Expand Down Expand Up @@ -2239,12 +2239,22 @@ def check_forward_port(self, ipv, port, protocol, toport=None, toaddr=None):
"port-forwarding is missing to-port AND to-addr")

def __forward_port_id(self, port, protocol, toport=None, toaddr=None):
self.check_forward_port("ipv4", port, protocol, toport, toaddr)
if check_single_address("ipv6", toaddr):
self.check_forward_port("ipv6", port, protocol, toport, toaddr)
else:
self.check_forward_port("ipv4", port, protocol, toport, toaddr)
return (portStr(port, "-"), protocol,
portStr(toport, "-"), str(toaddr))

def __forward_port(self, enable, zone, port, protocol, toport=None,
toaddr=None, mark_id=None, use_zone_transaction=None):

ipvs = [ ]
if check_single_address("ipv6", toaddr):
ipvs.append("ipv6")
else:
ipvs.append("ipv4")

if use_zone_transaction is None:
zone_transaction = self.new_zone_transaction(zone)
else:
Expand All @@ -2253,25 +2263,27 @@ def __forward_port(self, enable, zone, port, protocol, toport=None,
mark_str = "0x%x" % mark_id
port_str = portStr(port)

to = ""
if toaddr:
to += toaddr

filter_chain = "INPUT" if not toaddr else "FORWARD_IN"

if toport and toport != "":
to += ":%s" % portStr(toport, "-")

mark = [ "-m", "mark", "--mark", mark_str ]

if enable:
zone_transaction.add_chain("mangle", "PREROUTING")
zone_transaction.add_chain("nat", "PREROUTING")
zone_transaction.add_chain("filter", filter_chain)
zone_transaction.add_post(enable_ip_forwarding, "ipv4")

add_del = { True: "-A", False: "-D" }[enable]
for ipv in [ "ipv4" ]: # IPv4 only!
for ipv in ipvs:
to = ""
if toaddr:
if ipv == "ipv6":
to += "[%s]" % toaddr
else:
to += toaddr
if toport and toport != "":
to += ":%s" % portStr(toport, "-")

zone_transaction.add_post(enable_ip_forwarding, ipv)
target = DEFAULT_ZONE_TARGET.format(
chain=SHORTCUTS["PREROUTING"], zone=zone)
zone_transaction.add_rule(ipv,
Expand Down
6 changes: 3 additions & 3 deletions src/firewall/core/io/zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import shutil

from firewall.config import ETC_FIREWALLD
from firewall.functions import checkIP, checkIPnMask, checkIP6nMask, checkInterface, uniqify, max_zone_name_len, u2b_if_py2, check_mac, portStr
from firewall.functions import checkIP, checkIP6, checkIPnMask, checkIP6nMask, checkInterface, uniqify, max_zone_name_len, u2b_if_py2, check_mac, portStr
from firewall.core.base import DEFAULT_ZONE_TARGET, ZONE_TARGETS
from firewall.core.io.io_object import PY2, IO_Object, \
IO_Object_ContentHandler, IO_Object_XMLGenerator, check_port, \
Expand Down Expand Up @@ -210,7 +210,7 @@ def _check_config(self, config, item):
if fwd_port[2]:
check_port(fwd_port[2])
if fwd_port[3]:
if not checkIP(fwd_port[3]):
if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
raise FirewallError(
errors.INVALID_ADDR,
"to-addr '%s' is not a valid address" % fwd_port[3])
Expand Down Expand Up @@ -446,7 +446,7 @@ def startElement(self, name, attrs):
if to_port:
check_port(to_port)
if to_addr:
if not checkIP(to_addr):
if not checkIP(to_addr) and not checkIP6(to_addr):
raise FirewallError(errors.INVALID_ADDR,
"to-addr '%s' is not a valid address" \
% to_addr)
Expand Down
12 changes: 11 additions & 1 deletion src/tests/firewall-cmd_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ assert_good " --add-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_good " --query-forward-port port=66:proto=sctp:toport=66:toaddr=7.7.7.7 --zone=${default_zone}"
assert_good "--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_bad " --query-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_good " --add-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_good " --query-forward-port port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0:: --zone=${default_zone}"
assert_good "--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_bad " --query-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"

assert_bad "--permanent --add-forward-port=666" # no protocol
assert_good "--permanent --add-forward-port=port=11:proto=tcp:toport=22 --zone=${default_zone}"
Expand All @@ -525,6 +529,11 @@ assert_good "--permanent --add-forward-port=port=66:proto=sctp:toport=66:toad
assert_good "--permanent --query-forward-port port=66:proto=sctp:toport=66:toaddr=7.7.7.7 --zone=${default_zone}"
assert_good "--permanent --remove-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_bad "--permanent --query-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_good "--permanent --add-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_good "--permanent --query-forward-port port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0:: --zone=${default_zone}"
assert_good "--permanent --remove-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_bad "--permanent --query-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"


assert_good " --add-forward-port=port=88:proto=udp:toport=99 --add-forward-port port=100:proto=tcp:toport=200"
assert_good " --query-forward-port=port=100:proto=tcp:toport=200"
Expand Down Expand Up @@ -946,7 +955,8 @@ good_rules=(
'rule family="ipv6" masquerade'
'rule forward-port port="2222" to-port="22" to-addr="192.168.100.2" protocol="tcp" family="ipv4" source address="192.168.2.100"'
'rule forward-port port="66" to-port="666" to-addr="192.168.100.2" protocol="sctp" family="ipv4" source address="192.168.2.100"'
'rule forward-port port="99" to-port="999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"')
'rule forward-port port="99" to-port="999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"'
'rule forward-port port="99" to-port="10999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"')

for (( i=0;i<${#good_rules[@]};i++)); do
rule=${good_rules[${i}]}
Expand Down
7 changes: 6 additions & 1 deletion src/tests/firewall-offline-cmd_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ assert_good " --add-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_good " --query-forward-port port=66:proto=sctp:toport=66:toaddr=7.7.7.7 --zone=${default_zone}"
assert_good "--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_bad " --query-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7"
assert_good " --add-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_good " --query-forward-port port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0:: --zone=${default_zone}"
assert_good "--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"
assert_bad " --query-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::"

assert_good " --add-forward-port=port=88:proto=udp:toport=99 --add-forward-port port=100:proto=tcp:toport=200"
assert_good " --query-forward-port=port=100:proto=tcp:toport=200"
Expand Down Expand Up @@ -715,7 +719,8 @@ good_rules=(
'rule family="ipv6" masquerade'
'rule forward-port port="2222" to-port="22" to-addr="192.168.100.2" protocol="tcp" family="ipv4" source address="192.168.2.100"'
'rule forward-port port="66" to-port="666" to-addr="192.168.100.2" protocol="sctp" family="ipv4" source address="192.168.2.100"'
'rule forward-port port="99" to-port="999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"')
'rule forward-port port="99" to-port="999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"'
'rule forward-port port="99" to-port="10999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"')

for (( i=0;i<${#good_rules[@]};i++)); do
rule=${good_rules[${i}]}
Expand Down

0 comments on commit a62db0f

Please sign in to comment.