Snippets:Nginx geo local server address

# shell script
ip route add local 2001:db8::/64 dev lo
geo "$server_addr" $upstream_url {
    default 255.255.255.255;
    2001:db8::1 upstream-one.example:22;
    2001:db8::2 upstream-two.example:22;
}
stream { # or http
    server {
        listen [::]:22;
        location / {
            proxy_pass $upstream_url;
        }
    }
}

Assume 2001:db8::/64 is routed to your server. If someone connects to your SSH server via the destination IP address 2001:db8::1, perhaps via DNS, they will connect to upstream-one.example on port 22. If they connect to 2001:db8::2, then it will connect to upstream-two.example. Otherwise, the connection fails. You can still use a Unix domain socket, perhaps if the SSH server is running in a container, runs in inetd mode, and uses tcpsvd bound to a Unix domain socket.

In this configuration, the IP addresses act as service endpoints rather than host endpoints.

One advantage of doing this is that since there are no systems with an on-link route of 2001:db8::/64, all IP addresses in that range become usable. Even though this is not too important for IPv6, it is, however, useful for IPv4 since the .0 (network identifier) and .255 (broadcast) addresses suddenly become usable, if the 2001:db8::/64 addresses are substituted by a public IPv4 range such as 192.0.2.0/24. This is especially useful for delegations smaller than /24 (e.g. /28); for example, a /28 has 16 total addresses, but only 13 are usable on an actual network with those addresses; this configuration would allow all 16 addresses to be used.

IIRC, you do not need to set ip_nonlocal_bind=1, since :: will effectively bind to all addresses, including the entire range specified by the "ip" command above.

Fundamentally, the "geo" directive is similar to "map", except that it matches IP addresses instead of strings.