Snippets:Node.js NAT64 TCP relay

const net = require("net");
const ip = require("ip");
const nat64Prefix = ip.cidrSubnet('64:ff9b::/96');
function findOptionsByIP(s) {
    /* Given s.localAddress and s.localPort, convert the address
     * and port from the NAT64 prefix into an options object
     * containing the target IPv4 address
     *
     * Or use a map or JSON object to determine an arbitrary
     * destination based on the destination IP address of the
     * original TCP connection.
     */
    let localAddr = s.localAddress;
    let localPort = s.localPort;
    let remoteAddr = s.remoteAddress;
    let remotePort = s.remotePort;
    console.log(`[${remoteAddr}]:${remotePort} -> [${localAddr}]:${localPort}`);

    if (nat64Prefix.contains(localAddr)) {
        let addr_b = ip.toBuffer(localAddr);
        let translated_ipv4 = `${b[12]}.${b[13]}.${b[14]}.${b[15]}`;
        return {host: translated_ipv4, port: localPort};
    }
    return null;
}

net.createServer(function (s) {
    let options = findOptionsByIP(s);
    if (options) {
        let cc = net.createConnection(options, function(c) {
            s.pipe(cc);
            cc.pipe(s);
        });
   }
}).listen({fd: Number(process.env.CTRTOOL_NS_OPEN_FILE_FD_0)}); /* Use Python to create a transparent listening socket */

The procedure for creating the socket on $CTRTOOL_NS_OPEN_FILE_FD_0 is similar to the procedure as described in IPv6 Things/Configuration for s_telnet_server.

TODO: Error handling of net.createConnection

This will hopefully become a much better implementation of inet-relay written in a higher-level programming language. Again, the NAT64 is implemented as a high-level TCP transparent proxy server, rather than a packet translator.

Now that ns_open_file in ctrtool has been implemented, it might be useful to use that program to create a listening socket in a rootless container's network namespace, while still making outbound connections in the original namespace.

This is similar to Snippets:Nginx geo local server address, but with Node.js instead of nginx, and can also support arbitrary algorithms (like the ones used for NAT64) and headers (e.g. the PROXY protocol header).

For a much better version of this, check out Universal Relay.