OPNsense Forum

English Forums => Tutorials and FAQs => Topic started by: meyergru on November 22, 2023, 02:52:40 PM

Title: How (not) to expose services in your home network
Post by: meyergru on November 22, 2023, 02:52:40 PM
So now I am fed up with all these discussions about IPv6 and DynDNS shortcomings... beware, this is long!  :P


First, let's talk about IPv4 and how you did it back then.

In the old days (tm) of IPv4, you wanted to expose services on your firewall or your internal machines
(you will later see why this distinction is relevant) to the internet, but alas, your ISP did not give you a static IPv4.

Thus, you set up one or more dynamic DNS name(s) which your router updated via a DynDNS (for "dynamic DNS") provider and open up ports for your services via (D)NAT and be done with it.
Well, you probably had the problem that each service had to use a different port, but you could port-translate
to the destination machine. Thus, every machine could have another port even if the internal service always used the same one.

For IPv4, you also used NAT reflection, such that your clients can use the same external IP (and hence DNS name) from within your own network(s).


But now, it's 2023 and we have IPv6 (and sometimes even only IPv6).


Alas, despite of the abundance of IPv6 addresses, most ISPs only offer dynamic IPv6. So we probably
need DynDNS for IPv6 as well. But many DynDNS providers still do not support IPv6.
Even if they do, we still face problems:


Special case: You only have a routeable IPv6, because your ISP only offers CG-NAT for IPv4. Well, forget about the idea of exposing IPv4 services by pure firewall means anyway. You need to rely on a service to translate IPv4 to IPv6 for you or you do it yourself via a cloud VPS.

For what follows, I assume you have both inbound IPv4 and IPv6.

You will have to find ways around these DynDNS problems. We will get to this point later on.

Before that, let us discuss types of services. Roughly, we have these:


For type 1, I personally prefer to use HAproxy (There is a great tutorial on this by TheHellSite for OpnSense,
see https://forum.opnsense.org/index.php?topic=23339.0).
Because of termination at the firewall, the main advantages to this are:


Notes:


For type 2, you can (and probably should) still use HAproxy, but (mostly) you cannot have e. and f.
You can also expose type 2 services directly, but there are some catches:






Now how do we do that type of "dual" DynDNS?

As said earlier, with IPv6, every device gets their own IP, so now the distinction between your firewall and
your other devices becomes relevant (with IPv4, all used the WAN IP).
So, first thing to note: if have have multiple devices, you will need multiple DNS names.

As with IPv4, it is probably your router who does the dynamic DNS updates for you. With IPv6, it can usually do these updates only for itself. There are at least two reasons for this:

OpnSense has an (partial) answer to this because it can find either the IPv4 or the IPv6 of a specific interface (via "Check ip methods" "Interface [IPv4]" and "Interface [IPv6]") and provide the result via the macro __MYIP__. This is a "partial solution" because for DynDNS providers that can only accept both IP types in the same request, this will not work without a small trick.


The remedy to these problems is:



So, as an example, let us assume there are these devices:



Let us further assume that your ISP fives you a /56 IPv6 dynamic public delegation prefix (say dead:beef:feed:fa00::0/56) and you used the 8 network bits as "00" for your LAN and "ce" for your IoT VLAN1 (Be aware that OpnSense wants the network bits in decimal, so this would be 0 and 206, respectively).

In that case, you could configure three DynDNS names like so:




opnsense.dyndns-x.comdead:beef:feed:faXX:a8bb:ccff:fedd:eeff
lanserver.dyndns-x.comdead:beef:feed:fa00:1311:11ff:fe11:1111
iotdevice.dyndns-x.comdead:beef:feed:face:2022:22ff:fe22:2222

Note that you will have to find which interface is being chosen for outbound connections, thus the XX in the OpnSense IPv6.

Whenever your OpnSense gets another dynamic prefix (say cafe:babe:bedd:ab00::0/56), only the first 56 bits on all of these DynDNS entries get updated, because the DynDNS provider uses the new requesting IPv6 (cafe:babe:bedd:abXX:a8bb:ccff:fedd:eeff).

Of course, you have to set up firewall rules to access these devices. But for that, OpnSense has a firewall alias type of "Dynamic IPv6 Host" where you can specifiy the EUI-64 like given above plus the interface to which it is connected. The "Dynamic IPv6 Host" alias will get updated when the IPv6 prefix for the interface changes.

BTW: This assumes you use SLAAC for your internal clients and that they can handle IPv6 at all. For DHCPv6, you would have to use static reservations and use the lower 64 bits for the device instead of the EUI-64. If your clients cannot handle IPv6, many times you could still use HAproxy (there is a tutorial how to set this up) as an application-level gateway between IPv6 and IPv4.


Apart from the shortfalls I gave above, there are several weaknesses in current implementations:


@AdSchellevis: Fixing weaknesses 3 and 4 would be pure luxury!


Step-by-step instructions for the current, somewhat broken implementation:


Your OpnSense now has both IPv4 and IPv6 DNS addressability as "testit99.dns.army". Your other LAN client(s) can be addressed via the subdomain name(s) you have created (e.g. "name.testit99.dns.army". You can install IPv6 firewall rules to allow traffic as needed, but be careful.
Title: Re: How (not) to expose services in your home network
Post by: Seimus on November 22, 2023, 04:23:55 PM
This is golden!

Regards,
S.
Title: Re: How (not) to expose services in your home network
Post by: Patrick M. Hausen on November 22, 2023, 04:29:47 PM
Why not have your publicly accessible services registered in DynDNS by their current GUA from the systems running these services themselves?

I find proxying/reverse NAT for IPv6 rather fruitless. Getting rid of all that stuff is one of the points of IPv6. You can still have e.g. a crowdsec log collector on each and a central bouncer on the firewall.
Title: Re: How (not) to expose services in your home network
Post by: meyergru on November 22, 2023, 04:53:16 PM
Quote from: Patrick M. Hausen on November 22, 2023, 04:29:47 PM
Why not have your publicly accessible services registered in DynDNS by their current GUA from the systems running these services themselves?

I find proxying/reverse NAT for IPv6 rather fruitless. Getting rid of all that stuff is one of the points of IPv6. You can still have e.g. a crowdsec log collector on each and a central bouncer on the firewall.

The point is to offer both IPv4 and IPv6 services, preferably under a unified DNS name / URL. Some mobile providers do not offer IPv6, as well as some company and hotel WLANs. For these cases, IPv6 only won't cut it.

Also, I do not like my devices "polling" randomly for DynDNS updates. The firewall / router knows best when a connection is recreated. Apart from the difficulties with many DynDNS providers and the crude mechanims offered for IPv6 on different platforms, let alone with "dual stack". ddclient is a prominent example of this and @AdSchellevis did a better job at this (although it could be improved to support even more limited DynDNS providers).

As I said, having a name-based solution like HAproxy with all of the centralized management for TLS certificates instead of having to do the same for multiple clients (some of which do not even offer TLS) is a plus for me, too. Therefore, I like @TheHellSite's tutorial. This guide offers the missing step of how to do this for both dynamic IPv4 and IPv6. And you do not have to use proxying/NAT either. The guide explains how IPv6 prefixes can be used to do this for internal IPv6 clients as well.

Title: Re: How (not) to expose services in your home network
Post by: meyergru on February 08, 2024, 11:54:00 AM
I want to add another important warning to this tutorial:

If you aim to hide services behind "names" via HAproxy, do not use single- or multi-domain certificates and also, protect your DNS entries.

Reasoning:

If you are like me, part 8 of TheHellSite's great tutorial (https://forum.opnsense.org/index.php?topic=23339.0) may have led you to believe, that you could hide specific potentially vulnerable services behind a name that nobody besides you knows. You may be mistaken...

First off, "security by obscurity" is debatable anyway.

Second off: If the DNS zone of your names allows zone transfers, one could easily find all the names that are assigned. Because with the advent of IPv6, an IP-based scan is not feasible anyway, so an intelligent attacker may take another approach. Namely, he gets the names of sites he want to scan for vulnerabilities and connects to those instead of just randomly hitting at IPs.

So, protect your DNS entries. Either use zones that do not allow zone transfers or use a DNS wildcard in order to not list the names in the first place (this is also easier to manage if you want to add services later on).

Third off: You probably do not know about "certificate transparency (https://certificate.transparency.dev/)". Almost any CA takes part in this, including Letsencrypt. Any certificate that was issued by these CAs is publically shown. For an example, look here (https://www.nicsrs.com/check-ct-log) and enter your TLD.

Thus, you should never use any single or multi domain certificate but instead use something like "*.dyndns-x.com". Alas, most dyndns providers do not offer this. Probably, they offer "*.yourname.dyndns-x.com", YMMV.

What makes this complicated if that you either have to find a dyndns provider who offers that feature (plus having their DNS zones protected, too!) or use a CNAME from your own DNS zone and have means to control that yourself.

Part of the problem also is, that in order to use wildcard certificates with Letsencrypt, you have to use DNS-01 (https://letsencrypt.org/docs/challenge-types/) challenges, forcing you to update the DNS for the zones dynamically. If you do that with BIND, you either must make the whole zone dynamic or sub-delegate _acme-challenge.dyndns-x.com, which is not an easy task in itself and goes way beyond the scope of this tutorial.

What you should have learned by now is that the step-by-step instructions above do not cover this case of wildcard DNS names and therefore are unsafe to use if you aim to have your internal services completely hidden.
Title: Re: How (not) to expose services in your home network
Post by: meyergru on February 08, 2024, 12:02:33 PM
One little tidbit: If you use HAproxy with certificates for IMAP access as well, you should know that Dovecot does not handle OCSP stapling currently. So, if you enable OCSP "must staple" in your certificates for dual-use (HTTPS and IMAP/TLS), it will not work. The solution is to separate out the certificate(s) for IMAP, disable OCSP for that and use it for the IMAP frontend only.

I found that the hard way. What was really misleading was that my iPhone worked fine with such a certificate and Dovecot as a server, but Thunderbird did not.