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).