From 2c94114a3fe13ab9adc0be5b953a97584f0ab541 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 22 May 2024 21:31:32 +0200 Subject: nat: T6345: source NAT port mapping "fully-random" is superfluous in Kernel >=5.0 random - In kernel 5.0 and newer this is the same as fully-random. In earlier kernels the port mapping will be randomized using a seeded MD5 hash mix using source and destination address and destination port. https://git.netfilter.org/nftables/commit/?id=fbe27464dee4588d906492749251454 (cherry picked from commit 7fe568ca1672f1dfbd2b56ee3ef7a6ab48b03070) --- .../include/nat-translation-options.xml.i | 8 +- .../include/version/nat-version.xml.i | 2 +- smoketest/config-tests/nat-basic | 85 +++++++ smoketest/configs/nat-basic | 256 +++++++++++++++++++++ src/migration-scripts/nat/7-to-8 | 62 +++++ 5 files changed, 406 insertions(+), 7 deletions(-) create mode 100644 smoketest/config-tests/nat-basic create mode 100644 smoketest/configs/nat-basic create mode 100755 src/migration-scripts/nat/7-to-8 diff --git a/interface-definitions/include/nat-translation-options.xml.i b/interface-definitions/include/nat-translation-options.xml.i index 6b95de045..c8900590f 100644 --- a/interface-definitions/include/nat-translation-options.xml.i +++ b/interface-definitions/include/nat-translation-options.xml.i @@ -28,22 +28,18 @@ Port mapping options - random fully-random none + random none random Randomize source port mapping - - fully-random - Full port randomization - none Do not apply port randomization - (random|fully-random|none) + (random|none) none diff --git a/interface-definitions/include/version/nat-version.xml.i b/interface-definitions/include/version/nat-version.xml.i index 656da6e14..173e91ed3 100644 --- a/interface-definitions/include/version/nat-version.xml.i +++ b/interface-definitions/include/version/nat-version.xml.i @@ -1,3 +1,3 @@ - + diff --git a/smoketest/config-tests/nat-basic b/smoketest/config-tests/nat-basic new file mode 100644 index 000000000..9fea08b02 --- /dev/null +++ b/smoketest/config-tests/nat-basic @@ -0,0 +1,85 @@ +set interfaces ethernet eth0 offload rps +set interfaces ethernet eth0 disable +set interfaces ethernet eth1 offload gro +set interfaces ethernet eth1 offload gso +set interfaces ethernet eth1 offload rps +set interfaces ethernet eth1 offload sg +set interfaces ethernet eth1 offload tso +set interfaces ethernet eth2 offload gro +set interfaces ethernet eth2 offload gso +set interfaces ethernet eth2 offload rps +set interfaces ethernet eth2 offload sg +set interfaces ethernet eth2 offload tso +set interfaces ethernet eth3 offload gro +set interfaces ethernet eth3 offload gso +set interfaces ethernet eth3 offload rps +set interfaces ethernet eth3 offload sg +set interfaces ethernet eth3 offload tso +set interfaces bonding bond10 hash-policy 'layer3+4' +set interfaces bonding bond10 member interface 'eth2' +set interfaces bonding bond10 member interface 'eth3' +set interfaces bonding bond10 mode '802.3ad' +set interfaces bonding bond10 vif 50 address '192.168.189.1/24' +set interfaces loopback lo +set interfaces pppoe pppoe7 authentication password 'vyos' +set interfaces pppoe pppoe7 authentication username 'vyos' +set interfaces pppoe pppoe7 dhcpv6-options pd 0 interface bond10.50 address '1' +set interfaces pppoe pppoe7 dhcpv6-options pd 0 length '56' +set interfaces pppoe pppoe7 ip adjust-mss '1452' +set interfaces pppoe pppoe7 ipv6 address autoconf +set interfaces pppoe pppoe7 ipv6 adjust-mss '1432' +set interfaces pppoe pppoe7 mtu '1492' +set interfaces pppoe pppoe7 no-peer-dns +set interfaces pppoe pppoe7 source-interface 'eth1' +set service lldp interface eth1 disable +set service ntp allow-client address '192.168.189.0/24' +set service ntp server time1.vyos.net +set service ntp server time2.vyos.net +set service ntp listen-address '192.168.189.1' +set service ssh dynamic-protection +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 lease '604800' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 option default-router '192.168.189.1' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 option domain-name 'vyos.net' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 option name-server '1.1.1.1' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 option name-server '9.9.9.9' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 range 0 start '192.168.189.20' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 range 0 stop '192.168.189.254' +set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 subnet-id '1' +set service router-advert interface bond10.50 prefix ::/64 preferred-lifetime '2700' +set service router-advert interface bond10.50 prefix ::/64 valid-lifetime '5400' +set system config-management commit-revisions '100' +set system domain-name 'vyos.net' +set system host-name 'R1' +set system login user vyos authentication encrypted-password '$6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/' +set system login user vyos authentication plaintext-password '' +set system name-server '1.1.1.1' +set system name-server '9.9.9.9' +set system console device ttyS0 speed '115200' +set nat destination rule 1000 destination port '3389' +set nat destination rule 1000 inbound-interface name 'pppoe7' +set nat destination rule 1000 protocol 'tcp' +set nat destination rule 1000 translation address '192.168.189.5' +set nat destination rule 1000 translation port '3389' +set nat destination rule 10022 destination port '10022' +set nat destination rule 10022 inbound-interface name 'pppoe7' +set nat destination rule 10022 protocol 'tcp' +set nat destination rule 10022 translation address '192.168.189.2' +set nat destination rule 10022 translation port '22' +set nat destination rule 10300 destination port '10300' +set nat destination rule 10300 inbound-interface name 'pppoe7' +set nat destination rule 10300 protocol 'udp' +set nat destination rule 10300 translation address '192.168.189.2' +set nat destination rule 10300 translation port '10300' +set nat source rule 10 outbound-interface name 'eth1' +set nat source rule 10 source address '192.168.189.0/24' +set nat source rule 10 translation address 'masquerade' +set nat source rule 10 translation options port-mapping 'random' +set nat source rule 50 outbound-interface name 'pppoe7' +set nat source rule 50 protocol 'udp' +set nat source rule 50 source address '192.168.189.2' +set nat source rule 50 source port '10300' +set nat source rule 50 translation address 'masquerade' +set nat source rule 50 translation port '10300' +set nat source rule 100 outbound-interface name 'pppoe7' +set nat source rule 100 source address '192.168.189.0/24' +set nat source rule 100 translation address 'masquerade' diff --git a/smoketest/configs/nat-basic b/smoketest/configs/nat-basic new file mode 100644 index 000000000..52f369f34 --- /dev/null +++ b/smoketest/configs/nat-basic @@ -0,0 +1,256 @@ +interfaces { + bonding bond10 { + hash-policy "layer3+4" + member { + interface "eth2" + interface "eth3" + } + mode "802.3ad" + vif 50 { + address "192.168.189.1/24" + } + } + ethernet eth0 { + disable + offload { + gro + gso + rps + sg + tso + } + } + ethernet eth1 { + offload { + gro + gso + rps + sg + tso + } + } + ethernet eth2 { + offload { + gro + gso + rps + sg + tso + } + } + ethernet eth3 { + offload { + gro + gso + rps + sg + tso + } + } + loopback lo { + } + pppoe pppoe7 { + authentication { + password "vyos" + username "vyos" + } + dhcpv6-options { + pd 0 { + interface bond10.50 { + address "1" + } + length "56" + } + } + ip { + adjust-mss "1452" + } + ipv6 { + address { + autoconf + } + adjust-mss "1432" + } + mtu "1492" + no-peer-dns + source-interface "eth1" + } +} +nat { + destination { + rule 1000 { + destination { + port "3389" + } + inbound-interface { + name "pppoe7" + } + protocol "tcp" + translation { + address "192.168.189.5" + port "3389" + } + } + rule 10022 { + destination { + port "10022" + } + inbound-interface { + name "pppoe7" + } + protocol "tcp" + translation { + address "192.168.189.2" + port "22" + } + } + rule 10300 { + destination { + port "10300" + } + inbound-interface { + name "pppoe7" + } + protocol "udp" + translation { + address "192.168.189.2" + port "10300" + } + } + } + source { + rule 10 { + outbound-interface { + name "eth1" + } + source { + address "192.168.189.0/24" + } + translation { + address "masquerade" + options { + port-mapping fully-random + } + } + } + rule 50 { + outbound-interface { + name "pppoe7" + } + protocol "udp" + source { + address "192.168.189.2" + port "10300" + } + translation { + address "masquerade" + port "10300" + } + } + rule 100 { + outbound-interface { + name "pppoe7" + } + source { + address "192.168.189.0/24" + } + translation { + address "masquerade" + } + } + } +} +service { + dhcp-server { + shared-network-name LAN { + subnet 192.168.189.0/24 { + default-router "192.168.189.1" + domain-name "vyos.net" + lease "604800" + name-server "1.1.1.1" + name-server "9.9.9.9" + range 0 { + start "192.168.189.20" + stop "192.168.189.254" + } + } + } + } + lldp { + interface all { + } + interface eth1 { + disable + } + } + ntp { + allow-client { + address "192.168.189.0/24" + } + listen-address "192.168.189.1" + server time1.vyos.net { + } + server time2.vyos.net { + } + } + router-advert { + interface bond10.50 { + prefix ::/64 { + preferred-lifetime "2700" + valid-lifetime "5400" + } + } + } + ssh { + disable-host-validation + dynamic-protection { + } + } +} +system { + config-management { + commit-revisions "100" + } + conntrack { + modules { + ftp + h323 + nfs + pptp + sip + sqlnet + tftp + } + } + console { + device ttyS0 { + speed "115200" + } + } + domain-name "vyos.net" + host-name "R1" + login { + user vyos { + authentication { + encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ + plaintext-password "" + } + } + } + name-server "1.1.1.1" + name-server "9.9.9.9" + syslog { + global { + facility all { + level "info" + } + facility local7 { + level "debug" + } + } + } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "bgp@5:broadcast-relay@1:cluster@2:config-management@1:conntrack@5:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@7:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2" +// Release version: 1.4.0-epa3 diff --git a/src/migration-scripts/nat/7-to-8 b/src/migration-scripts/nat/7-to-8 new file mode 100755 index 000000000..ab2ffa6d3 --- /dev/null +++ b/src/migration-scripts/nat/7-to-8 @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# T6345: random - In kernel 5.0 and newer this is the same as fully-random. +# In earlier kernels the port mapping will be randomized using a seeded +# MD5 hash mix using source and destination address and destination port. +# drop fully-random from CLI + +from sys import argv,exit +from vyos.configtree import ConfigTree + +if len(argv) < 2: + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +if not config.exists(['nat']): + # Nothing to do + exit(0) + +for direction in ['source', 'destination']: + # If a node doesn't exist, we obviously have nothing to do. + if not config.exists(['nat', direction]): + continue + + # However, we also need to handle the case when a 'source' or 'destination' sub-node does exist, + # but there are no rules under it. + if not config.list_nodes(['nat', direction]): + continue + + for rule in config.list_nodes(['nat', direction, 'rule']): + port_mapping = ['nat', direction, 'rule', rule, 'translation', 'options', 'port-mapping'] + if config.exists(port_mapping): + tmp = config.return_value(port_mapping) + if tmp == 'fully-random': + config.set(port_mapping, value='random') + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) -- cgit v1.2.3