mirror of
https://github.com/toreanderson/clatd.git
synced 2026-04-20 00:20:53 +00:00
Compare commits
11 Commits
v2.0.0
...
feature/ip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
009c3f74a9 | ||
|
|
4e1c7fa71f | ||
|
|
d9f274bbe7 | ||
|
|
ae8da007c6 | ||
|
|
5e085f1b17 | ||
|
|
06c567b9cb | ||
|
|
f86f1cabb8 | ||
|
|
f812070f60 | ||
|
|
f91d96b991 | ||
|
|
b93a5526a5 | ||
|
|
6f98967f0e |
8
Makefile
8
Makefile
@@ -7,9 +7,11 @@ DNF_OR_YUM:=$(shell which dnf || which yum)
|
||||
SYSTEMCTL:=$(shell which systemctl)
|
||||
TAYGA:=$(shell which tayga)
|
||||
|
||||
all:
|
||||
|
||||
install:
|
||||
# Install the main script
|
||||
install -m0755 clatd $(DESTDIR)$(PREFIX)/sbin/clatd
|
||||
install -D -m0755 clatd $(DESTDIR)$(PREFIX)/sbin/clatd
|
||||
# Install manual page if pod2man is installed
|
||||
pod2man --name clatd --center "clatd - a CLAT implementation for Linux" --section 8 README.pod $(DESTDIR)$(PREFIX)/share/man/man8/clatd.8 && gzip -f9 $(DESTDIR)$(PREFIX)/share/man/man8/clatd.8 || echo "pod2man is required to generate manual page"
|
||||
# Install systemd service file if applicable for this system
|
||||
@@ -20,8 +22,8 @@ install:
|
||||
|
||||
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 iproute2 nftables tayga; fi
|
||||
if test -x "$(APT_GET)"; then $(APT_GET) -y install perl-base perl-modules libnet-ip-perl libnet-dns-perl libjson-perl iproute2 nftables tayga; fi
|
||||
# .rpm/DNF/YUM-based distros
|
||||
if test -x "$(DNF_OR_YUM)"; then $(DNF_OR_YUM) -y install perl perl-IPC-Cmd perl-Net-IP perl-Net-DNS 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-File-Temp perl-JSON 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 <URL: https://fedoraproject.org/wiki/EPEL> and try again, or install TAYGA <URL: http://www.litech.org/tayga> directly from source."; exit 1; fi
|
||||
|
||||
29
README.pod
29
README.pod
@@ -241,17 +241,32 @@ with using B<clatd> as a SIIT-DC Edge Relay (I<RFC 7756>).
|
||||
=item B<dns64-servers=srv1,[srv2,..]> (default: use system resolver)
|
||||
|
||||
Comma-separated list of DNS64 servers to use when discovering the PLAT prefix
|
||||
using the method described in RFC 7050. By default, the system resolver is
|
||||
used, but it might be useful to override this in case your ISP doesn't provide
|
||||
you with a DNS64-enabled name server, and you want to test B<clatd> using any of
|
||||
the public DNS64/NAT64 instances on the internet. The first PLAT prefix
|
||||
encountered will be used.
|
||||
using the method described in I<RFC 7050>. By default, B<clatd> will first try
|
||||
to determine if systemd-networkd is aware of a PLAT prefix (learned from the
|
||||
PREF64 Router Advertisement option, cf. I<RFC 8781>), falling back on using
|
||||
DNS64 discovery towards the system resolver if it isn't.
|
||||
|
||||
It might be useful to override this in case your network does not advertise the
|
||||
PREF64 RA option, your ISP doesn't provide you with a DNS64-enabled name
|
||||
server, and you want to test B<clatd> using any of the public DNS64/NAT64
|
||||
instances on the internet. The first PLAT prefix encountered will be used.
|
||||
|
||||
=item B<cmd-ip=path> (default: assume in $PATH)
|
||||
|
||||
Path to the B<ip> binary from the iproute2 package available at
|
||||
L<https://www.kernel.org/pub/linux/utils/net/iproute2>. Required.
|
||||
|
||||
=item B<cmd-networkctl=path> (default: assume in $PATH)
|
||||
|
||||
Path to the B<networkctl> binary from systemd-networkd. Required in order to
|
||||
use any PLAT prefix discovered by systemd-networkd from the PREF64 Router
|
||||
Advertisement option (see I<RFC 8781> and the I<UsePREF64> option in
|
||||
I<systemd.network(5)> for more information). The first prefix returned is used,
|
||||
any others are ignored.
|
||||
|
||||
To prevent PLAT prefix discovery via systemd-networkd from being attempted, set
|
||||
this to an empty string.
|
||||
|
||||
=item B<cmd-nft=path> (default: assume in $PATH)
|
||||
|
||||
Path to the B<nft> binary from the nftables package available at
|
||||
@@ -493,9 +508,9 @@ SOFTWARE.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
ip(8), nft(8), tayga(8), tayga.conf(5)
|
||||
ip(8), nft(8), systemd.network(5), tayga(8), tayga.conf(5)
|
||||
|
||||
RFC 6052, RFC 6145, RFC 6146, RFC 6877, RFC 7050, RFC 7335 RFC 7755, RFC 7756,
|
||||
RFC 7757
|
||||
RFC 7757, RFC 8781
|
||||
|
||||
=cut
|
||||
|
||||
171
clatd
171
clatd
@@ -27,7 +27,7 @@ use strict;
|
||||
use IPC::Cmd qw(can_run);
|
||||
use Net::IP;
|
||||
|
||||
my $VERSION = "2.0.0";
|
||||
my $VERSION = "2.1.0";
|
||||
|
||||
#
|
||||
# Populate the global config hash with the default values
|
||||
@@ -42,6 +42,8 @@ $CFG{"clat-v4-addr"} = "192.0.0.1"; # from RFC 7335
|
||||
$CFG{"clat-v6-addr"} = "shared"; # re-use primary address from host OS
|
||||
$CFG{"dns64-servers"} = undef; # use system resolver by default
|
||||
$CFG{"cmd-ip"} = "ip"; # assume in $PATH
|
||||
$CFG{"cmd-ipxlat-ctl"} = "ipxlat-ctl"; # assume in $PATH
|
||||
$CFG{"cmd-networkctl"} = "networkctl"; # assume in $PATH
|
||||
$CFG{"cmd-nft"} = "nft"; # assume in $PATH
|
||||
$CFG{"cmd-tayga"} = "tayga"; # assume in $PATH
|
||||
$CFG{"cmd-ufw"} = "ufw"; # assume in $PATH
|
||||
@@ -61,6 +63,7 @@ $CFG{"v4-defaultroute-replace"} = 0; # replace existing v4 defaultroute?
|
||||
$CFG{"v4-defaultroute-metric"} = 2048; # metric for the IPv4 defaultroute
|
||||
$CFG{"v4-defaultroute-mtu"} = 1260; # MTU for the IPv4 defaultroute
|
||||
$CFG{"v4-defaultroute-advmss"} = 0; # TCP MSS for the IPv4 defaultroute
|
||||
$CFG{"xlat-engine"} = undef; # which translation engine to use
|
||||
|
||||
|
||||
#
|
||||
@@ -329,7 +332,7 @@ sub find_rfc7050_wka {
|
||||
# up to see if the well-known hostname 'ipv4only.arpa' resolves to an IPv6
|
||||
# address, if so there is a high chance of DNS64 being used.
|
||||
#
|
||||
sub get_plat_prefix {
|
||||
sub get_plat_prefix_from_dns64 {
|
||||
p("Performing DNS64-based PLAT prefix discovery (cf. RFC 7050)");
|
||||
|
||||
require Net::DNS;
|
||||
@@ -356,7 +359,8 @@ sub get_plat_prefix {
|
||||
$res->nameservers(map {
|
||||
Net::IP->new($_)->version() == 4 ? "::ffff:$_" : $_;
|
||||
} $res->nameservers);
|
||||
d2("Nameservers after Net::DNS bug workaround: ", $res->nameservers);
|
||||
d2("Nameservers after Net::DNS bug workaround: ",
|
||||
join(" ", $res->nameservers));
|
||||
|
||||
my $pkt = $res->query('ipv4only.arpa', 'AAAA');
|
||||
if(!$pkt) {
|
||||
@@ -390,13 +394,69 @@ sub get_plat_prefix {
|
||||
p("No PLAT prefix could be discovered, using fallback");
|
||||
return $CFG{"plat-fallback-prefix"};
|
||||
} else {
|
||||
p("No PLAT prefix could be discovered. Your ISP probably doesn't provide",
|
||||
p("No PLAT prefix could be discovered. Your connection probably doesn't provide",
|
||||
" NAT64/DNS64 PLAT service. Exiting.");
|
||||
cleanup_and_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# This function attempts request a PLAT prefix from systemd-networkd, which
|
||||
# systemd-networkd will know about if the Router Advertisements contain the
|
||||
# PREF64 option defined in RFC 8781, and systemd-networkd is configured with
|
||||
# UsePREF64=true (not the default). The first prefix seen is used, subsequent
|
||||
# ones are ignored.
|
||||
#
|
||||
sub get_plat_prefix_from_networkd {
|
||||
if(!can_run(cfg("cmd-networkctl"))) {
|
||||
d(cfg("cmd-networkctl"), " is not installed or not exectutable, skipping");
|
||||
return;
|
||||
}
|
||||
p("Attempting to query systemd-networkd for PLAT prefix (cf. RFC 8781)");
|
||||
open(my $fd, '-|', cfg("cmd-networkctl"), qw(--json=short status))
|
||||
or err(cfg("cmd-networkctl"), " failed to execute");
|
||||
my @out = <$fd>;
|
||||
if(!close($fd)) {
|
||||
p("'networkctl status' failed, trying DNS64 PLAT prefix discovery");
|
||||
return;
|
||||
}
|
||||
|
||||
require JSON;
|
||||
my $status = JSON::decode_json("@out");
|
||||
|
||||
return unless($status->{"Interfaces"});
|
||||
|
||||
for my $interface (@{$status->{"Interfaces"}}) {
|
||||
next if(!$interface->{"NDisc"}->{"PREF64"});
|
||||
|
||||
d2($interface->{"Name"}, " PREF64 bytes: ",
|
||||
join(" ", @{$interface->{"NDisc"}->{"PREF64"}->[0]->{"Prefix"}}),
|
||||
" / ", $interface->{"NDisc"}->{"PREF64"}->[0]->{"PrefixLength"});
|
||||
|
||||
# PREF64 is an array of bytes, convert to IPv6 string representation
|
||||
my @bytes = @{$interface->{"NDisc"}->{"PREF64"}->[0]->{"Prefix"}};
|
||||
my $ipstr;
|
||||
for (my $i = 0; $i < @bytes;) {
|
||||
$ipstr .= sprintf("%02x%02x", $bytes[$i++], $bytes[$i++]);
|
||||
$ipstr .= ":" if($i < @bytes);
|
||||
}
|
||||
$ipstr .= "/" . $interface->{"NDisc"}->{"PREF64"}->[0]->{"PrefixLength"};
|
||||
|
||||
d2("String representation: $ipstr");
|
||||
|
||||
# Run the result through Net::IP to ensure we have a valid IPv6 string
|
||||
# and also to convert it to compact format.
|
||||
my $ip = Net::IP->new($ipstr, 6)
|
||||
or err("Failed to convert PREF64 bytes array to IPv6 string format");
|
||||
|
||||
my $prefix = $ip->short() . "/" . $ip->prefixlen();
|
||||
d("Obtained PLAT prefix $prefix from systemd-networkd");
|
||||
return $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# This function figures out which network interface on the system faces the
|
||||
# PLAT/NAT64. We need this when generating an IPv6 address for the CLAT, when
|
||||
@@ -608,6 +668,7 @@ sub get_clat_v6_addr {
|
||||
#
|
||||
my $cleanup_remove_tayga_clat_dev; # true if having created it
|
||||
my $cleanup_remove_nat46_clat_dev; # true if having created it
|
||||
my $cleanup_remove_ipxlat_clat_dev; # true if having created it
|
||||
my $cleanup_delete_taygaconf; # true if having made a temp confile
|
||||
my $cleanup_zero_forwarding_sysctl; # zero forwarding sysctl if set
|
||||
my @cleanup_accept_ra_sysctls; # accept_ra sysctls to be reset to '1'
|
||||
@@ -639,6 +700,9 @@ sub cleanup_and_exit {
|
||||
print $nat46_control_fh "del ", cfg("clat-dev"), "\n";
|
||||
close($nat46_control_fh) or err("close($nat46_control_fh: $!");
|
||||
}
|
||||
if(defined($cleanup_remove_ipxlat_clat_dev)) {
|
||||
cmd(\&w, cfg("cmd-ip"), qw(link delete dev), cfg("clat-dev"));
|
||||
}
|
||||
if(defined($cleanup_zero_forwarding_sysctl)) {
|
||||
d("Cleanup: Resetting forwarding sysctl to 0");
|
||||
sysctl("net/ipv6/conf/all/forwarding", 0);
|
||||
@@ -676,11 +740,11 @@ sub cleanup_and_exit {
|
||||
}
|
||||
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",
|
||||
"from", cfg("internal-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"));
|
||||
cfg("internal-clat-v6-addr"));
|
||||
}
|
||||
|
||||
exit($exitcode);
|
||||
@@ -770,7 +834,9 @@ p("Starting clatd v$VERSION by Tore Anderson <tore\@fud.no>");
|
||||
#
|
||||
# Step 1: Fill in any essential blanks in the configuration by auto-detecting
|
||||
# any missing values.
|
||||
$CFG{"plat-prefix"} ||= get_plat_prefix();
|
||||
$CFG{"plat-prefix"} ||= get_plat_prefix_from_networkd()
|
||||
unless($CFG{"dns64-servers"});
|
||||
$CFG{"plat-prefix"} ||= get_plat_prefix_from_dns64();
|
||||
if(!$CFG{"plat-prefix"}) {
|
||||
w("No PLAT prefix was discovered or specified; 464XLAT cannot work.");
|
||||
exit 0;
|
||||
@@ -785,6 +851,7 @@ if(!$CFG{"plat-prefix"}) {
|
||||
$ip->prefixlen() != 64 and
|
||||
$ip->prefixlen() != 56 and
|
||||
$ip->prefixlen() != 48 and
|
||||
$ip->prefixlen() != 40 and
|
||||
$ip->prefixlen() != 32) {
|
||||
err("PLAT prefix $CFG{'plat-prefix'} has an invalid prefix length ",
|
||||
"(see RFC 6052 section 2.2)");
|
||||
@@ -811,6 +878,16 @@ if($CFG{"clat-v6-addr"} eq "shared") {
|
||||
$CFG{"clat-v6-addr"} = get_clat_v6_addr();
|
||||
}
|
||||
|
||||
# Since ipxlat does not support EAM, we'll need to do SNAT66 from the RFC 6052
|
||||
# representaion of the CLAT IPv4 address used internally. It is sometimes
|
||||
# necessary to refer to this address instead of the CLAT IPv6 address, so
|
||||
# create a separate entry in the config hash for that. The other engines (tayga
|
||||
# and nat46) supports using EAM to map directly between the CLAT IPv4 address
|
||||
# and CLAT IPv6 address without any going via any intermediate RFC6052 address,
|
||||
# so default to having the two addresses identical (if using ipxlat, the
|
||||
# internal one will be overridden later).
|
||||
$CFG{"internal-clat-v6-addr"} = $CFG{"clat-v6-addr"};
|
||||
|
||||
# Fill defaults for proxynd-enable and ctmark for clat-v6-addr!=shared
|
||||
if(!defined($CFG{"proxynd-enable"})) {
|
||||
$CFG{"proxynd-enable"} = 1;
|
||||
@@ -847,17 +924,49 @@ if(cfgbool("v4-conncheck-enable") and !cfgbool("v4-defaultroute-replace")) {
|
||||
d("Skipping IPv4 connectivity check at user request");
|
||||
}
|
||||
|
||||
# Let's figure out if there's nat46 kernel module loaded
|
||||
my $nat46_controlfile = "/proc/net/nat46/control";
|
||||
my $use_nat46 = (-e $nat46_controlfile);
|
||||
|
||||
my $nat46_controlfile = "/proc/net/nat46/control";
|
||||
|
||||
#
|
||||
# Auto-detect which translation engine to use if not specified in config
|
||||
if(!cfg("xlat-engine") and (-e $nat46_controlfile)) {
|
||||
p("Using translation engine: nat46");
|
||||
$CFG{"xlat-engine"} = "nat46";
|
||||
} elsif(!cfg("xlat-engine") and can_run(cfg("cmd-ipxlat-ctl"))) {
|
||||
p("Using translation engine: ipxlat");
|
||||
$CFG{"xlat-engine"} = "ipxlat";
|
||||
my $pfx = Net::IP->new($CFG{"plat-prefix"});
|
||||
my $fmt = $pfx->ip;
|
||||
if($pfx->prefixlen == 96) {
|
||||
$fmt =~ s/0000:0000$/%02x%02x:%02x%02x/;
|
||||
} elsif($pfx->prefixlen == 64) {
|
||||
$fmt =~ s/00:0000:0000:0000$/%02x:%02x%02x:%02x00:0000/;
|
||||
} elsif($pfx->prefixlen == 56) {
|
||||
$fmt =~ s/00:0000:0000:0000:0000$/%02x:00%02x:%02x%02x:0000:0000/;
|
||||
} elsif($pfx->prefixlen == 48) {
|
||||
$fmt =~ s/0000:0000:0000:0000:0000$/%02x%02x:00%02x:%02x00:0000:0000/;
|
||||
} elsif($pfx->prefixlen == 40) {
|
||||
$fmt =~ s/00:0000:0000:0000:0000:0000$/%02x:%02x%02x:00%02x:0000:0000:0000/;
|
||||
} elsif($pfx->prefixlen == 32) {
|
||||
$fmt =~ s/0000:0000:0000:0000:0000:0000$/%02x%02x:%02x%02x:0000:0000:0000:0000/;
|
||||
}
|
||||
my $ip = sprintf($fmt, split(/\./, $CFG{"clat-v4-addr"}));
|
||||
$CFG{"internal-clat-v6-addr"} = Net::IP->new($ip)->short;
|
||||
p("Using internal CLAT IPv6 address: ", $CFG{"internal-clat-v6-addr"});
|
||||
} elsif(!cfg("xlat-engine") and can_run(cfg("cmd-tayga"))) {
|
||||
p("Using translation engine: TAYGA");
|
||||
$CFG{"xlat-engine"} = "tayga";
|
||||
} elsif(!cfg("xlat-engine")) {
|
||||
err("No supported translation engine available. Please install TAYGA or ensure ",
|
||||
"either the nat46 or ipxlat kernel modules is loaded.");
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Write out the TAYGA config file, either to the user-specified location,
|
||||
# or to a temporary file (which we'll delete later)
|
||||
#
|
||||
unless($use_nat46) {
|
||||
if(cfg("xlat-engine") eq "tayga") {
|
||||
my $tayga_conffile = cfg("tayga-conffile");
|
||||
my $tayga_conffile_fh;
|
||||
if(!$tayga_conffile) {
|
||||
@@ -916,11 +1025,11 @@ if(can_run(cfg("cmd-ufw"))) {
|
||||
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",
|
||||
"from", cfg("internal-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"));
|
||||
cfg("internal-clat-v6-addr"));
|
||||
$cleanup_remove_ufw_rules = 1;
|
||||
}
|
||||
}
|
||||
@@ -967,14 +1076,17 @@ close($fd) or err("'ip -6 rule show prio 0 table local' failed");
|
||||
# route to the corresponding IPv6 address, and possibly an IPv4 default route
|
||||
#
|
||||
p("Creating and configuring up CLAT device '", cfg("clat-dev"), "'");
|
||||
if($use_nat46) {
|
||||
if(cfg("xlat-engine") eq "nat46") {
|
||||
my $nat46_control_fh;
|
||||
open($nat46_control_fh, ">$nat46_controlfile") or
|
||||
err("Could not open nat46 control socket for writing");
|
||||
print $nat46_control_fh "add ", cfg("clat-dev"), "\n";
|
||||
close($nat46_control_fh) or err("close($nat46_control_fh: $!");
|
||||
$cleanup_remove_nat46_clat_dev = 1;
|
||||
} else {
|
||||
} elsif(cfg("xlat-engine") eq "ipxlat") {
|
||||
cmd(\&err, cfg("cmd-ip"), qw(link add name), cfg("clat-dev"), qw(type ipxlat));
|
||||
$cleanup_remove_ipxlat_clat_dev = 1;
|
||||
} elsif(cfg("xlat-engine") eq "tayga") {
|
||||
cmd(\&err, cfg("cmd-tayga"), "--config", cfg("tayga-conffile"), "--mktun",
|
||||
cfgint("debug") ? "-d" : "");
|
||||
$cleanup_remove_tayga_clat_dev = 1;
|
||||
@@ -982,10 +1094,10 @@ if($use_nat46) {
|
||||
cmd(\&err, cfg("cmd-ip"), qw(link set up dev), cfg("clat-dev"));
|
||||
cmd(\&err, cfg("cmd-ip"), qw(-4 address add), cfg("clat-v4-addr"),
|
||||
"dev", cfg("clat-dev"));
|
||||
cmd(\&err, cfg("cmd-ip"), qw(-6 route add), cfg("clat-v6-addr"),
|
||||
cmd(\&err, cfg("cmd-ip"), qw(-6 route add), cfg("internal-clat-v6-addr"),
|
||||
"dev", cfg("clat-dev"), "table", cfgint("route-table"));
|
||||
cmd(\&err, cfg("cmd-ip"), qw(-6 rule add prio 0 from),
|
||||
cfg("plat-prefix"), "to", cfg("clat-v6-addr"),
|
||||
cfg("plat-prefix"), "to", cfg("internal-clat-v6-addr"),
|
||||
cfgint("ctmark") ? ("fwmark", cfgint("ctmark")) : (),
|
||||
"table", cfg("route-table"));
|
||||
$cleanup_remove_clat_iprule = 1;
|
||||
@@ -996,13 +1108,13 @@ if(cfgint("ctmark")) {
|
||||
or err("'nft -f-' failed to execute");
|
||||
print $fd "add table ip6 clatd\n";
|
||||
print $fd "add chain ip6 clatd prerouting ",
|
||||
"{ type filter hook prerouting priority 0; }\n";
|
||||
"{ type filter hook prerouting priority mangle; }\n";
|
||||
print $fd "add rule ip6 clatd prerouting",
|
||||
" iif ", cfg("clat-dev"),
|
||||
" ip6 saddr ", cfg("clat-v6-addr"),
|
||||
" ip6 saddr ", cfg("internal-clat-v6-addr"),
|
||||
" ip6 daddr ", cfg("plat-prefix"),
|
||||
" ct mark set ", cfgint("ctmark"),
|
||||
# set meta mark as well, to placate firewalld's IPv6_rpfilter
|
||||
# set meta mark as well, to placate firewalld's IPv6_rpfilter and NixOS' rpfilter rules
|
||||
" meta mark set ", cfgint("ctmark"), " counter\n";
|
||||
print $fd "add rule ip6 clatd prerouting",
|
||||
" iif ", cfg("plat-dev"),
|
||||
@@ -1010,6 +1122,15 @@ if(cfgint("ctmark")) {
|
||||
" ip6 daddr ", cfg("clat-v6-addr"),
|
||||
" ct mark ", cfgint("ctmark"),
|
||||
" meta mark set ct mark counter\n";
|
||||
if(cfg("clat-v6-addr") ne cfg("internal-clat-v6-addr")) {
|
||||
print $fd "add chain ip6 clatd postrouting ",
|
||||
"{ type nat hook postrouting priority srcnat; }\n";
|
||||
print $fd "add rule ip6 clatd postrouting",
|
||||
" iif ", cfg("clat-dev"),
|
||||
" ip6 saddr ", cfg("internal-clat-v6-addr"),
|
||||
" ip6 daddr ", cfg("plat-prefix"),
|
||||
" snat to ", cfg("clat-v6-addr");
|
||||
}
|
||||
close($fd) or err("'nft -f-' failed");
|
||||
$cleanup_remove_nftable = 1;
|
||||
}
|
||||
@@ -1056,7 +1177,7 @@ if(cfg("script-up")) {
|
||||
# All preparation done! We can now start nat46 or TAYGA, which will handle the actual
|
||||
# translation of IP packets.
|
||||
#
|
||||
if($use_nat46){
|
||||
if(cfg("xlat-engine") eq "nat46") {
|
||||
p("Setting up nat46 kernel module");
|
||||
my $nat46_control_fh;
|
||||
open($nat46_control_fh, ">$nat46_controlfile") or
|
||||
@@ -1072,7 +1193,13 @@ if($use_nat46){
|
||||
$SIG{'INT'} = \&cleanup_handler;
|
||||
$SIG{'TERM'} = \&cleanup_handler;
|
||||
sleep();
|
||||
} else {
|
||||
} elsif(cfg("xlat-engine") eq "ipxlat") {
|
||||
cmd(\&err, cfg("cmd-ipxlat-ctl"), cfg("clat-dev"), "pool6", cfg("plat-prefix"));
|
||||
# Nothing more to do here, we just set up a cleanup handler and sleep forever.
|
||||
$SIG{'INT'} = \&cleanup_handler;
|
||||
$SIG{'TERM'} = \&cleanup_handler;
|
||||
sleep();
|
||||
} elsif(cfg("xlat-engine") eq "tayga") {
|
||||
my $tayga_conffile = cfg("tayga-conffile");
|
||||
p("Starting up TAYGA, using config file '$tayga_conffile'");
|
||||
|
||||
|
||||
18
ipxlat-ctl
Executable file
18
ipxlat-ctl
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# This is a wrapper around the python ynl cli included with the kernel that
|
||||
# mimics the documented behaviour of the ipxlat-ctl tool available at
|
||||
# https://codeberg.org/IPv6-Monostack/ipxlat, but which I haven't been able to
|
||||
# make work. You'll need to ensure the tool is somewhere in $PATH.
|
||||
|
||||
PATH=/usr/src/kernels/ipxlat-net-next/tools/net/ynl/pyynl:$PATH
|
||||
|
||||
dev="$1"
|
||||
prefix="$3"
|
||||
|
||||
IID=$(< /sys/class/net/$dev/ifindex)
|
||||
ADDR_HEX=$(python3 -c 'import ipaddress,sys; print(ipaddress.IPv6Address(sys.argv[1]).packed.hex())' ${prefix%/*})
|
||||
PREFIXLEN=${prefix#*/}
|
||||
JSON='{"ifindex": '"$IID"', "config": {"xlat-prefix6": { "prefix": "'$ADDR_HEX'", "prefix-len": '$PREFIXLEN'}}}'
|
||||
|
||||
cli.py --family ipxlat --do dev-set --json "$JSON"
|
||||
Reference in New Issue
Block a user