diff --git a/Makefile b/Makefile index 988e5e6..4ed9e8e 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,6 @@ installdeps: # .deb/apt-get based distros if test -x "$(APT_GET)"; then $(APT_GET) -y install perl-base perl-modules libnet-ip-perl libnet-dns-perl libio-socket-ip-perl iproute2 nftables tayga; fi # .rpm/DNF/YUM-based distros - if test -x "$(DNF_OR_YUM)"; then $(DNF_OR_YUM) -y install perl perl-Net-IP perl-Net-DNS perl-IO-Socket-IP perl-File-Temp iproute nftables; fi + if test -x "$(DNF_OR_YUM)"; then $(DNF_OR_YUM) -y install perl perl-IPC-Cmd perl-Net-IP perl-Net-DNS perl-IO-Socket-IP perl-File-Temp iproute nftables; fi # If necessary, try to install the TAYGA .rpm using dnf/yum. It is unfortunately not available in all .rpm based distros (in particular CentOS/RHEL). if test -x "$(DNF_OR_YUM)" && test ! -x "$(TAYGA)"; then $(DNF_OR_YUM) -y install tayga || echo "ERROR: Failed to install TAYGA using dnf/yum, the package is probably not included in your distro. Try enabling the EPEL repo and try again, or install TAYGA directly from source."; exit 1; fi diff --git a/README.pod b/README.pod index c34fff4..410b0f4 100644 --- a/README.pod +++ b/README.pod @@ -262,6 +262,18 @@ L. Required if I is set. Path to the B binary from the TAYGA package available at L. Required. +=item B (default: assume in $PATH) + +Path to the B binary from the UFW local firewall framework available at +L commonly seen on Debian-based distributions. If +this command is present on the system, and B reports that the +firewall is active, B will add firewall rules ensuring traffic between +the CLAT and the PLAT prefix is allowed when it is starting up, and remove them +when it is shutting down. + +If you don't want B to add and remove UFW firewall rules, set this to an +empty string. + =item B (default: I) Controls whether or not B should enable IPv6 forwarding if necessary. diff --git a/clatd b/clatd index 9e6fe53..8ded271 100755 --- a/clatd +++ b/clatd @@ -24,6 +24,7 @@ # clatd(8) for more information. # use strict; +use IPC::Cmd qw(can_run); use Net::IP; my $VERSION = "1.6nat46"; @@ -43,6 +44,7 @@ $CFG{"dns64-servers"} = undef; # use system resolver by default $CFG{"cmd-ip"} = "ip"; # assume in $PATH $CFG{"cmd-nft"} = "nft"; # assume in $PATH $CFG{"cmd-tayga"} = "tayga"; # assume in $PATH +$CFG{"cmd-ufw"} = "ufw"; # assume in $PATH $CFG{"ctmark"} = undef; # match ctmark for routing pkts to CLAT $CFG{"forwarding-enable"} = 1; # enable ipv6 forwarding? $CFG{"plat-dev"} = undef; # PLAT-facing device, default detect @@ -604,6 +606,7 @@ my $cleanup_zero_proxynd_sysctl; # zero proxy_ndp sysctl if set my $cleanup_remove_proxynd_entry, # true if having added proxynd entry my $cleanup_remove_nftable; # true if having added an nftable my $cleanup_remove_clat_iprule; # true if having added clat iprule +my $cleanup_remove_ufw_rules; # true if having added ufw rules my $cleanup_restore_local_iprule_prio; # true if having reordered local iprule my @cleanup_restore_v4_defaultroutes; # temporarily replaced defaultroutes @@ -662,6 +665,14 @@ sub cleanup_and_exit { d("Cleanup: Removing ip rule for redirecting inbound traffic to CLAT"); cmd(\&w, cfg("cmd-ip"), qw(-6 rule del prio 0 table), cfg("route-table")); } + if(defined($cleanup_remove_ufw_rules)) { + cmd(\&w, cfg("cmd-ufw"), qw(route delete allow in on), cfg("clat-dev"), + "from", cfg("clat-v6-addr"), qw(out on), cfg("plat-dev"), "to", + cfg("plat-prefix")); + cmd(\&w, cfg("cmd-ufw"), qw(route delete allow in on), cfg("plat-dev"), + "from", cfg("plat-prefix"), qw(out on), cfg("clat-dev"), "to", + cfg("clat-v6-addr")); + } exit($exitcode); } @@ -885,6 +896,30 @@ if(cfgbool("forwarding-enable")) { } } +# +# Add firewall rules to allow PLAT-CLAT traffic if a supported local firewall +# framework is present and active +# +if(can_run(cfg("cmd-ufw"))) { + open(my $fd, '-|', cfg("cmd-ufw"), "status") + or err("'ufw status' failed to execute"); + while(<$fd>) { + if(/^Status: active$/) { + p("UFW local firewall framework active, allowing CLAT-PLAT traffic"); + cmd(\&err, cfg("cmd-ufw"), qw(route allow in on), cfg("clat-dev"), + "from", cfg("clat-v6-addr"), qw(out on), cfg("plat-dev"), "to", + cfg("plat-prefix")); + cmd(\&err, cfg("cmd-ufw"), qw(route allow in on), cfg("plat-dev"), + "from", cfg("plat-prefix"), qw(out on), cfg("clat-dev"), "to", + cfg("clat-v6-addr")); + $cleanup_remove_ufw_rules = 1; + } + } + close($fd) or err("'ufw status' failed"); +} else { + d("UFW command '", cfg("cmd-ufw"), "' not found, not installing UFW rules"); +} + # # Enable ND proxy for the CLAT's IPv6 address on the interface facing the PLAT #