1. 21

  2. 3

    Just a heads up: It is important to firewall those IPv6 subnets used for IPv4 translation. That way you’ll avoid anyone just directly accessing the application throught a specially crafted IPv6 address. If the subnets were to be world accessible, you’d make it possible to disguise as any random IPv4 client IP address.

    1. 3

      Having used mismatches in IPv4 vs IPv6 firewall rules to my advantage many times in penetration tests, this is a point I really appreciate. (Here’s a good old paper on it in case anyone is unfamililar…)

      In this case, though, I’m not sure I see the concern. These applications are being intentionally exposed, and there is no authentication or authorization happening on the proxy by design. The application on the back end is handling it all, so connecting directly instead of via the SNI proxy would not buy anything for an attacker.

      Or am I misreading your point?

      1. 1

        My point is that the IPv4 address is encoded into the last 32 bits of the IPv6 server address. So if the application were to use an allowlist based on IP addresses (e.g.: only expose this login endpoint if from the office IP address), or a rate limiter, or you’d like to read the correct IP address in the logs, you’d make a decision based on an incorrect (and potentially maliciously crafted) IP address.

        Let’s say the IPv6 address for the service in question is 2001:0db8:85a3::1 and that this is available in DNS as an AAAA record. Then let’s say the proxy would use the same publicly routable subnet for the IPv4-to-IPv6 conversion. If you were to enter the specially crafted IPv6 address in the browser, you’d make the application think you’re coming from a specific IPv4 address.

        You’d want to firewall off everything but the public service address from all other than localhost.

        1. 1

          My point is that the IPv4 address is encoded into the last 32 bits of the IPv6 server address.

          By my read, it’s encoded into the last 32 bits of the proxy-constructed IPv6 “client” address:

          snid embeds the client’s IP address in the lower 32 bits of the source address which it uses to connect to the backend.

          which means the backend app would need to also ignore the first 32 bits in order for this to be an issue. I’d never discount this, because I’ve seen quite a bit of dangerously braindead behavior that’s adjacent to it. But the fact that the web applications described in the post expect to receive unproxied IPv6 requests also, according to the article:

          The AAAA record for a webapp is the dedicated IPv6 address, and the A record is the shared IPv4 address. Thus, IPv6 clients connect directly to the webapp, while IPv4 clients are proxied via snid.

          makes me think that what you’re describing shouldn’t be a concern in the context the author is posting about.

          1. 2

            Ah, okay. Good to get it cleared up – thanks :)

            So to sum it up:

            1. The proxy gets a request from an IPv4 address.
            2. The proxy chooses an internal IPv6 address that isn’t publicly routable and encodes the IPv4 address in the chosen internal IPv6 address (last 32 bits of the chosen source IPv6 address).
            3. The applications uses the reverse logic and extracts the client’s real IPv4 address.

            I must say, that is a neat trick. Glad I now understand it correctly.

      2. 3

        This is one of the big things that “NAT is not a security measure!” people forget about: yes it is.

        1. 5

          No it isn’t

          Firewalls are a security measure.

          1. 3

            More specifically, NAT is not a security measure. A sensible firewall policy is a security measure. NAT deployments require a firewall, though not always one with a sensible policy. A lot of consumer NAT things let you designate a single internal IP that all inbound connections go to if there isn’t an explicit forwarding rule configured for that port, making that device just as insecure as one directly connected to the Internet, combined with all of the disadvantages of NAT. In contrast, a simple deny-all-inbound policy on a stateful firewall gives you all of the advantages of NAT and requires less powerful hardware to implement with the same number of connections / packet rates.

        2. 3

          I am excited for a future where we can strip away the myriad NAT and proxy layers that have been built up to serve microservices (especially in k8s). Sounds like the path to that future is IPv6.

          I believe a single packet flowing through a k8s loadbalancer to an app on another node has to be copied something like 12-14 times (DNAT and SNAT on both sides, in and out of kernel space, etc.) which could be improved considerably with IPV6 replacing all of that NATing.

          1. 2

            To make Encrypted Client Hello work with snid, I just need to ensure that the decoy SNI hostname resolves to the IPv6 address of the backend server.

            How does this work? Is the decoy host name for a true host name predictable? In that case, what value does this even add?

            1. 1

              I really like this. At this time, I will probably still keep using Caddy as a reverse proxy in every situation I can think of where I might use this in anger, but this has a lot of appeal.

              Has anyone who has tried this exercised it with ESNI?