I had a similar proposal a couple of years ago, which is almost the same as this one, with one notable difference.
Instead of communicating the IP through the proxy protocol, I had envisioned the IPv4 address could be encoded in the IPv6 source address form the proxy; you’d simply have to give the proxy a /96 for itself.
But before I was able to implement it, someone else already did it better than I ever could, although they used the PROXY protocol, like in this article; sniproxy by dlundquist does everything this article mentions, and I’ve been running it in front of multiple projects myself.
Although when I looked at the Github issues back then, it seemed that this project was a lot more popular for setting up Netflix proxies than it was for the purpose in this article.
Author here. The PR https://github.com/dlundquist/sniproxy/pull/372 implements a PoC for your suggestion. I did not want to use this method because downstream software (let’s say NGINX / applications, etc.) does not support it in an easy way.
The solution here is built on the expectation that most downstream software understand what is a PROXY protocol or we can use a proper reverse proxy to make them understand it.
So BTW, unsure if I misunderstood your comment:
; sniproxy by dlundquist does everything this article mentions, and I’ve been running it in front of multiple projects myself.
Yes, sniproxy was used in this article, someone showed me https://github.com/jameysharp/sniproxy-rs which is interesting too.
But any SNI-enabled proxy can do the trick here.
Although when I looked at the Github issues back then, it seemed that this project was a lot more popular for setting up Netflix proxies than it was for the purpose in this article.
And censorship evasion measures! Anyway, not surprising given SNI is particularly powerful and ESNI even better for this.
I noticed! I think this patch is Linux-only, so it doesn’t help me much, but it’s cool to see someone with the same idea.
downstream software (let’s say NGINX / applications, etc.) does not support it in an easy way.
That’s the neat part; they don’t have to. You can always extract the IPv4 address from the IPv6 address in your log, even if software in between doesn’t know what’s going on.
If you also want reverse DNS to work, you’d need an interesting DNS server. But I don’t do reverse queries just for logging.
So BTW, unsure if I misunderstood your comment:
Yes, sniproxy was used in this article
Ah, I see, it is I who mistunderstood the article. I thought you implemented another reverse proxy, but you actually made a Nix setup with sniproxy. I only saw services.sniproxy, but I’m not very familiar with Nix so I didn’t notice it was the same thing.
And censorship evasion measures! Anyway, not surprising given SNI is particularly powerful and ESNI even better for this.
That’s the neat part; they don’t have to. You can always extract the IPv4 address from the IPv6 address in your log, even if software in between doesn’t know what’s going on.
Indeed, but I’m not exactly sure stuff like goaccess support it out of the box, but I do agree.
Ah, I see, it is I who mistunderstood the article. I thought you implemented a reverse proxy, but you made a Nix setup with sniproxy. I only saw service.sniproxy, but I’m not very familiar with Nix so I didn’t notice it was the same thing.
Indeed, I am using a sniproxy NixOS module to configure sniproxy because it gives me a lot of flexibility and abstraction as I host 30+ proxied vhosts.
ESNI [ECH now] makes SNI proxying harder for hosts that you don’t own, because without the private key, your man in the middle doesn’t know where to proxy anymore. I don’t think this particular sniproxy implementation is getting support for it anytime soon.
Oh makes sense. It’s a bit sad though. I really like not being custodian of the keys, ugh.
Congrats on submitting the (by my count) 9th Lobsters article that mentions IPv6 in the title! A real tragedy that so few devs are interested in this stuff.
Wouldn’t SIIT serve this purpose better? My router doesn’t support SIIT so I may be misunderstanding it, but I believe your router would do the translation at Layer 3. Then you could do SNI or “Host” header routing like normal in some other proxy like nginx inside your IPv6-only network. The IPv4 source IP would be visible in logs and can be blocked with normal tools since it just appears as a padded IPv6 IP.
Hmm, uncertain if SIIT fits the bill. As you remarked, it will still produce an overhead to process those IPv6-only logs.
But I am definitely going to play with SIIT to solve other issues for non-TLS stuff.
For the HardenedBSD build infrastructure, which I host out of my home behind a single IPv4 address and tunneled IPv6 (with HE’s TunnelBroker service), I use nginx as a web reverse proxy. Below is a sanitized version of the nginx configuration.
All hostname-related records in the hardenedbsd.lan domain have ONLY an IPv6 AAAA record. No A records exist for *.hardenedbsd.lan.
Hmm, it seems like to me you are re-doing encryption right? It’s not exactly a SNI technique per se, is it?
I wonder though what is the impact of connecting two TLS segments like this in terms of performance or traffic increase.
Cryptographic key material is required regardless. In this context, SNI is used simply to determine which host the client is trying to reach. nginx doesn’t require any extra configuration parameters for SNI (meaning: full native transparent support for SNI) when SSL/TLS support is compiled in.
Cryptographic key material is required regardless.
This is the part I don’t understand; what is the minimal requirement for the material? dhparams or?
So if I understand well, your NGINX cannot “dump” the plaintext communication between a client and git.hardenedbsd.org for example, right? Do you have any link on the matter? I am definitely confused a bit on this.
If you take a look to my article, I never use any cryptographic key material. See https://github.com/dlundquist/sniproxy for examples too. It never use any cryptographic key material, neither it does decrypt the traffic.
So that’s why I’m wondering why this is needed in your case.
I had a similar proposal a couple of years ago, which is almost the same as this one, with one notable difference.
Instead of communicating the IP through the proxy protocol, I had envisioned the IPv4 address could be encoded in the IPv6 source address form the proxy; you’d simply have to give the proxy a /96 for itself.
But before I was able to implement it, someone else already did it better than I ever could, although they used the PROXY protocol, like in this article; sniproxy by dlundquist does everything this article mentions, and I’ve been running it in front of multiple projects myself.
Although when I looked at the Github issues back then, it seemed that this project was a lot more popular for setting up Netflix proxies than it was for the purpose in this article.
Author here. The PR https://github.com/dlundquist/sniproxy/pull/372 implements a PoC for your suggestion. I did not want to use this method because downstream software (let’s say NGINX / applications, etc.) does not support it in an easy way.
The solution here is built on the expectation that most downstream software understand what is a PROXY protocol or we can use a proper reverse proxy to make them understand it.
So BTW, unsure if I misunderstood your comment:
Yes, sniproxy was used in this article, someone showed me https://github.com/jameysharp/sniproxy-rs which is interesting too. But any SNI-enabled proxy can do the trick here.
And censorship evasion measures! Anyway, not surprising given SNI is particularly powerful and ESNI even better for this.
I noticed! I think this patch is Linux-only, so it doesn’t help me much, but it’s cool to see someone with the same idea.
That’s the neat part; they don’t have to. You can always extract the IPv4 address from the IPv6 address in your log, even if software in between doesn’t know what’s going on.
If you also want reverse DNS to work, you’d need an interesting DNS server. But I don’t do reverse queries just for logging.
Ah, I see, it is I who mistunderstood the article. I thought you implemented another reverse proxy, but you actually made a Nix setup with sniproxy. I only saw services.sniproxy, but I’m not very familiar with Nix so I didn’t notice it was the same thing.
ESNI [ECH now] makes SNI proxying harder for hosts that you don’t own, because without the private key, your man in the middle doesn’t know where to proxy anymore. I don’t think this particular sniproxy implementation is getting support for it anytime soon.
Indeed, but I’m not exactly sure stuff like
goaccess
support it out of the box, but I do agree.Indeed, I am using a sniproxy NixOS module to configure sniproxy because it gives me a lot of flexibility and abstraction as I host 30+ proxied vhosts.
Oh makes sense. It’s a bit sad though. I really like not being custodian of the keys, ugh.
Congrats on submitting the (by my count) 9th Lobsters article that mentions IPv6 in the title! A real tragedy that so few devs are interested in this stuff.
Wouldn’t SIIT serve this purpose better? My router doesn’t support SIIT so I may be misunderstanding it, but I believe your router would do the translation at Layer 3. Then you could do SNI or “Host” header routing like normal in some other proxy like nginx inside your IPv6-only network. The IPv4 source IP would be visible in logs and can be blocked with normal tools since it just appears as a padded IPv6 IP.
Hmm, uncertain if SIIT fits the bill. As you remarked, it will still produce an overhead to process those IPv6-only logs. But I am definitely going to play with SIIT to solve other issues for non-TLS stuff.
I found a few more submissions with “ipv6” in the title: https://gist.github.com/gustafe/607aafbddfa7624509ff31e3f5213d36
They are ordered in reverse submission date order.
Thanks! I’ll read every one! Maybe the native search didn’t like the number “6” or something
Hehe, it seems to be “smarter” than just looking at the titles.
The result above is from scraping every submission title.
For the HardenedBSD build infrastructure, which I host out of my home behind a single IPv4 address and tunneled IPv6 (with HE’s TunnelBroker service), I use nginx as a web reverse proxy. Below is a sanitized version of the nginx configuration.
All hostname-related records in the
hardenedbsd.lan
domain have ONLY an IPv6 AAAA record. No A records exist for*.hardenedbsd.lan
.Here’s the
nginx.conf
file:As a bonus, here’s a snippet of the unbound config file for the HardenedBSD build infrastructure DNS server:
Hmm, it seems like to me you are re-doing encryption right? It’s not exactly a SNI technique per se, is it? I wonder though what is the impact of connecting two TLS segments like this in terms of performance or traffic increase.
nginx is doing SNI behind-the-scenes automatically for me.
But then, what is the
ssl_certificate
/ssl_certificate_key
used for? SNI should not require any TLS certificates as far as I understand it?Cryptographic key material is required regardless. In this context, SNI is used simply to determine which host the client is trying to reach. nginx doesn’t require any extra configuration parameters for SNI (meaning: full native transparent support for SNI) when SSL/TLS support is compiled in.
This is the part I don’t understand; what is the minimal requirement for the material? dhparams or?
So if I understand well, your NGINX cannot “dump” the plaintext communication between a client and git.hardenedbsd.org for example, right? Do you have any link on the matter? I am definitely confused a bit on this.
Doesn’t TLS require cryptographic key material? This is just regular HTTPS with TLS and SNI. I’m unsure as to the source of your confusion…
If you take a look to my article, I never use any cryptographic key material. See https://github.com/dlundquist/sniproxy for examples too. It never use any cryptographic key material, neither it does decrypt the traffic. So that’s why I’m wondering why this is needed in your case.
I wonder, could you use something like Boundary or Teleport for SSH where TLS is built in? So you do v6 to the proxy and that does v4 to the target.
I find it a lot easier to just set up an SSH jump host (hop host) on the IPv4 address, and use
-o ProxyJump hop.$DOMAIN
.Or even set up your
~/.ssh/config
: