CGNAT is for access to legacy IPv4 only.
For some reason, OpenSSH devs refuse to fix this issue, so I have to patch it myself:
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -26,6 +26,7 @@
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <linux/ipv6.h>
#include <ctype.h>
#include <errno.h>
@@ -370,6 +371,11 @@ ssh_create_socket(struct addrinfo *ai)
if (options.ip_qos_interactive != INT_MAX)
set_sock_tos(sock, options.ip_qos_interactive);
+ if (ai->ai_family == AF_INET6 && options.bind_address == NULL) {
+ int val = IPV6_PREFER_SRC_PUBLIC;
+ setsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &val, sizeof(val));
+ }
+
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL && options.bind_interface == NULL)
return sock;It boilds down to using a Linux-specific API, though it's really BSD that is lacking support for a standard (RFC 5014).
The largest IPv6 deployments in the world are mobile carriers, which are full of stateful firewalls, DPI, and mid-path translation. The difference is that when connections drop it gets blamed on the wireless rather than the network infrastructure.
Also, fun fact: net.ipv4.tcp_keepalive_* applies to IPv6 too. The "ipv4" is just a naming artifact.
The constrained resource there is only firewall-side memory, though, as opposed to that plus (IP, port) tuples for CG-NAT.
I highly doubt you get "random" data over ipv6. There are more ipv6 addresses than there are atoms on the planet.
For example, receiving traffic from a given address is a pretty good indicator that there's somebody there possibly worth port scanning.
And where there has once been somebody, there or in the same neighborhood (subnet) might be somebody else, now or in the future.