mirror of
https://github.com/toreanderson/clatd.git
synced 2026-04-20 16:40:37 +00:00
Compare commits
2 Commits
master
...
feature/ip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
009c3f74a9 | ||
|
|
4e1c7fa71f |
97
clatd
97
clatd
@@ -42,6 +42,7 @@ $CFG{"clat-v4-addr"} = "192.0.0.1"; # from RFC 7335
|
|||||||
$CFG{"clat-v6-addr"} = "shared"; # re-use primary address from host OS
|
$CFG{"clat-v6-addr"} = "shared"; # re-use primary address from host OS
|
||||||
$CFG{"dns64-servers"} = undef; # use system resolver by default
|
$CFG{"dns64-servers"} = undef; # use system resolver by default
|
||||||
$CFG{"cmd-ip"} = "ip"; # assume in $PATH
|
$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-networkctl"} = "networkctl"; # assume in $PATH
|
||||||
$CFG{"cmd-nft"} = "nft"; # assume in $PATH
|
$CFG{"cmd-nft"} = "nft"; # assume in $PATH
|
||||||
$CFG{"cmd-tayga"} = "tayga"; # assume in $PATH
|
$CFG{"cmd-tayga"} = "tayga"; # assume in $PATH
|
||||||
@@ -62,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-metric"} = 2048; # metric for the IPv4 defaultroute
|
||||||
$CFG{"v4-defaultroute-mtu"} = 1260; # MTU 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{"v4-defaultroute-advmss"} = 0; # TCP MSS for the IPv4 defaultroute
|
||||||
|
$CFG{"xlat-engine"} = undef; # which translation engine to use
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -666,6 +668,7 @@ sub get_clat_v6_addr {
|
|||||||
#
|
#
|
||||||
my $cleanup_remove_tayga_clat_dev; # true if having created it
|
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_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_delete_taygaconf; # true if having made a temp confile
|
||||||
my $cleanup_zero_forwarding_sysctl; # zero forwarding sysctl if set
|
my $cleanup_zero_forwarding_sysctl; # zero forwarding sysctl if set
|
||||||
my @cleanup_accept_ra_sysctls; # accept_ra sysctls to be reset to '1'
|
my @cleanup_accept_ra_sysctls; # accept_ra sysctls to be reset to '1'
|
||||||
@@ -697,6 +700,9 @@ sub cleanup_and_exit {
|
|||||||
print $nat46_control_fh "del ", cfg("clat-dev"), "\n";
|
print $nat46_control_fh "del ", cfg("clat-dev"), "\n";
|
||||||
close($nat46_control_fh) or err("close($nat46_control_fh: $!");
|
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)) {
|
if(defined($cleanup_zero_forwarding_sysctl)) {
|
||||||
d("Cleanup: Resetting forwarding sysctl to 0");
|
d("Cleanup: Resetting forwarding sysctl to 0");
|
||||||
sysctl("net/ipv6/conf/all/forwarding", 0);
|
sysctl("net/ipv6/conf/all/forwarding", 0);
|
||||||
@@ -734,11 +740,11 @@ sub cleanup_and_exit {
|
|||||||
}
|
}
|
||||||
if(defined($cleanup_remove_ufw_rules)) {
|
if(defined($cleanup_remove_ufw_rules)) {
|
||||||
cmd(\&w, cfg("cmd-ufw"), qw(route delete allow in on), cfg("clat-dev"),
|
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"));
|
cfg("plat-prefix"));
|
||||||
cmd(\&w, cfg("cmd-ufw"), qw(route delete allow in on), cfg("plat-dev"),
|
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",
|
"from", cfg("plat-prefix"), qw(out on), cfg("clat-dev"), "to",
|
||||||
cfg("clat-v6-addr"));
|
cfg("internal-clat-v6-addr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
exit($exitcode);
|
exit($exitcode);
|
||||||
@@ -845,6 +851,7 @@ if(!$CFG{"plat-prefix"}) {
|
|||||||
$ip->prefixlen() != 64 and
|
$ip->prefixlen() != 64 and
|
||||||
$ip->prefixlen() != 56 and
|
$ip->prefixlen() != 56 and
|
||||||
$ip->prefixlen() != 48 and
|
$ip->prefixlen() != 48 and
|
||||||
|
$ip->prefixlen() != 40 and
|
||||||
$ip->prefixlen() != 32) {
|
$ip->prefixlen() != 32) {
|
||||||
err("PLAT prefix $CFG{'plat-prefix'} has an invalid prefix length ",
|
err("PLAT prefix $CFG{'plat-prefix'} has an invalid prefix length ",
|
||||||
"(see RFC 6052 section 2.2)");
|
"(see RFC 6052 section 2.2)");
|
||||||
@@ -871,6 +878,16 @@ if($CFG{"clat-v6-addr"} eq "shared") {
|
|||||||
$CFG{"clat-v6-addr"} = get_clat_v6_addr();
|
$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
|
# Fill defaults for proxynd-enable and ctmark for clat-v6-addr!=shared
|
||||||
if(!defined($CFG{"proxynd-enable"})) {
|
if(!defined($CFG{"proxynd-enable"})) {
|
||||||
$CFG{"proxynd-enable"} = 1;
|
$CFG{"proxynd-enable"} = 1;
|
||||||
@@ -907,17 +924,49 @@ if(cfgbool("v4-conncheck-enable") and !cfgbool("v4-defaultroute-replace")) {
|
|||||||
d("Skipping IPv4 connectivity check at user request");
|
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,
|
# Write out the TAYGA config file, either to the user-specified location,
|
||||||
# or to a temporary file (which we'll delete later)
|
# 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 = cfg("tayga-conffile");
|
||||||
my $tayga_conffile_fh;
|
my $tayga_conffile_fh;
|
||||||
if(!$tayga_conffile) {
|
if(!$tayga_conffile) {
|
||||||
@@ -976,11 +1025,11 @@ if(can_run(cfg("cmd-ufw"))) {
|
|||||||
if(/^Status: active$/) {
|
if(/^Status: active$/) {
|
||||||
p("UFW local firewall framework active, allowing CLAT-PLAT traffic");
|
p("UFW local firewall framework active, allowing CLAT-PLAT traffic");
|
||||||
cmd(\&err, cfg("cmd-ufw"), qw(route allow in on), cfg("clat-dev"),
|
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"));
|
cfg("plat-prefix"));
|
||||||
cmd(\&err, cfg("cmd-ufw"), qw(route allow in on), cfg("plat-dev"),
|
cmd(\&err, cfg("cmd-ufw"), qw(route allow in on), cfg("plat-dev"),
|
||||||
"from", cfg("plat-prefix"), qw(out on), cfg("clat-dev"), "to",
|
"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;
|
$cleanup_remove_ufw_rules = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1027,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
|
# route to the corresponding IPv6 address, and possibly an IPv4 default route
|
||||||
#
|
#
|
||||||
p("Creating and configuring up CLAT device '", cfg("clat-dev"), "'");
|
p("Creating and configuring up CLAT device '", cfg("clat-dev"), "'");
|
||||||
if($use_nat46) {
|
if(cfg("xlat-engine") eq "nat46") {
|
||||||
my $nat46_control_fh;
|
my $nat46_control_fh;
|
||||||
open($nat46_control_fh, ">$nat46_controlfile") or
|
open($nat46_control_fh, ">$nat46_controlfile") or
|
||||||
err("Could not open nat46 control socket for writing");
|
err("Could not open nat46 control socket for writing");
|
||||||
print $nat46_control_fh "add ", cfg("clat-dev"), "\n";
|
print $nat46_control_fh "add ", cfg("clat-dev"), "\n";
|
||||||
close($nat46_control_fh) or err("close($nat46_control_fh: $!");
|
close($nat46_control_fh) or err("close($nat46_control_fh: $!");
|
||||||
$cleanup_remove_nat46_clat_dev = 1;
|
$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",
|
cmd(\&err, cfg("cmd-tayga"), "--config", cfg("tayga-conffile"), "--mktun",
|
||||||
cfgint("debug") ? "-d" : "");
|
cfgint("debug") ? "-d" : "");
|
||||||
$cleanup_remove_tayga_clat_dev = 1;
|
$cleanup_remove_tayga_clat_dev = 1;
|
||||||
@@ -1042,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(link set up dev), cfg("clat-dev"));
|
||||||
cmd(\&err, cfg("cmd-ip"), qw(-4 address add), cfg("clat-v4-addr"),
|
cmd(\&err, cfg("cmd-ip"), qw(-4 address add), cfg("clat-v4-addr"),
|
||||||
"dev", cfg("clat-dev"));
|
"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"));
|
"dev", cfg("clat-dev"), "table", cfgint("route-table"));
|
||||||
cmd(\&err, cfg("cmd-ip"), qw(-6 rule add prio 0 from),
|
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")) : (),
|
cfgint("ctmark") ? ("fwmark", cfgint("ctmark")) : (),
|
||||||
"table", cfg("route-table"));
|
"table", cfg("route-table"));
|
||||||
$cleanup_remove_clat_iprule = 1;
|
$cleanup_remove_clat_iprule = 1;
|
||||||
@@ -1059,7 +1111,7 @@ if(cfgint("ctmark")) {
|
|||||||
"{ type filter hook prerouting priority mangle; }\n";
|
"{ type filter hook prerouting priority mangle; }\n";
|
||||||
print $fd "add rule ip6 clatd prerouting",
|
print $fd "add rule ip6 clatd prerouting",
|
||||||
" iif ", cfg("clat-dev"),
|
" iif ", cfg("clat-dev"),
|
||||||
" ip6 saddr ", cfg("clat-v6-addr"),
|
" ip6 saddr ", cfg("internal-clat-v6-addr"),
|
||||||
" ip6 daddr ", cfg("plat-prefix"),
|
" ip6 daddr ", cfg("plat-prefix"),
|
||||||
" ct mark set ", cfgint("ctmark"),
|
" ct mark set ", cfgint("ctmark"),
|
||||||
# set meta mark as well, to placate firewalld's IPv6_rpfilter and NixOS' rpfilter rules
|
# set meta mark as well, to placate firewalld's IPv6_rpfilter and NixOS' rpfilter rules
|
||||||
@@ -1070,6 +1122,15 @@ if(cfgint("ctmark")) {
|
|||||||
" ip6 daddr ", cfg("clat-v6-addr"),
|
" ip6 daddr ", cfg("clat-v6-addr"),
|
||||||
" ct mark ", cfgint("ctmark"),
|
" ct mark ", cfgint("ctmark"),
|
||||||
" meta mark set ct mark counter\n";
|
" 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");
|
close($fd) or err("'nft -f-' failed");
|
||||||
$cleanup_remove_nftable = 1;
|
$cleanup_remove_nftable = 1;
|
||||||
}
|
}
|
||||||
@@ -1116,7 +1177,7 @@ if(cfg("script-up")) {
|
|||||||
# All preparation done! We can now start nat46 or TAYGA, which will handle the actual
|
# All preparation done! We can now start nat46 or TAYGA, which will handle the actual
|
||||||
# translation of IP packets.
|
# translation of IP packets.
|
||||||
#
|
#
|
||||||
if($use_nat46){
|
if(cfg("xlat-engine") eq "nat46") {
|
||||||
p("Setting up nat46 kernel module");
|
p("Setting up nat46 kernel module");
|
||||||
my $nat46_control_fh;
|
my $nat46_control_fh;
|
||||||
open($nat46_control_fh, ">$nat46_controlfile") or
|
open($nat46_control_fh, ">$nat46_controlfile") or
|
||||||
@@ -1132,7 +1193,13 @@ if($use_nat46){
|
|||||||
$SIG{'INT'} = \&cleanup_handler;
|
$SIG{'INT'} = \&cleanup_handler;
|
||||||
$SIG{'TERM'} = \&cleanup_handler;
|
$SIG{'TERM'} = \&cleanup_handler;
|
||||||
sleep();
|
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");
|
my $tayga_conffile = cfg("tayga-conffile");
|
||||||
p("Starting up TAYGA, using config file '$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