diff --git a/_drafts/hosting_at_home_p1.md b/_drafts/hosting_at_home_p1.md new file mode 100644 index 0000000..27ce9cc --- /dev/null +++ b/_drafts/hosting_at_home_p1.md @@ -0,0 +1,38 @@ +--- +layout: post +author: hexaitos +title: Hosting my websites at home – Delegating an IPv6 prefix from my FRITZ!Box to my OPNsense +--- + +A few months ago, I built my own home server which I have mostly been using as a NAS and for running a couple of other services like Immich which I’ve been accessing via a Tailscale VPN connection. However, I also have a bunch of websites that I have been hosting on a VPS; and while that works quite well, I wanted to find out if it was possible to host them on my own server as a sort of fallback / backup. The main problem here is that I am behind CGNAT which means that I do not have a publically accessible IPv4 address (not even a dynamic one); I do, however, get my own – and apparently static – /59 IPv6 prefix. + +This post is the first in a series of posts I will (hopefully) be writing. This one will focus on how I delegated an IPv6 prefix to my OPNsense installation. The other parts will focus mainly on how I made my IPv6-only server accessible even from IPv4-only networks. I am _not_ saying that anything I will be describing is necessarily the best way of going about it (I don’t really have all that much experience with IPv6 yet) but it’s what’s been working for me. If you have any ideas, comments or critique, feel free to [contact me](/contact). + +## My network +I should probably start off by explaining my network setup. I get cable (coax) internet from a German ISP called Vodafone. I used to have their provided router, but since it was absolutely terrible, I decided to buy my own, namely a FRITZ!Box 6660 Cable. + +**The IPv4 setup is relatively simple to explain**: My server is running Proxmox and it’s connected to my FRITZ!Box router. The Proxmox host itself gets an IP in my router’s LAN network (192.168.178.0/24). Running on Proxmox as a virtual machine is my OPNsense installation with two network interfaces, WAN and LAN. The WAN interface is connected to my router and I assigned it a static IP in the 192.168.178.0/24 network mentioned earlier. The LAN interface of my OPNsense installation is in the 10.10.10.0/24 network and all other VMs running on Proxmox are connected to that interface. Thus, all the traffic of all my VMs goes through my OPNsense installation and all my VMs have a private IPv4 address in aforementioned network. + +**The IPv6 setup is going to be a bit more complicated**. This is mostly because I don’t really have that much experience with IPv6 yet. Even at work we don’t really use IPv6 (even though I would *really* like to). As mentioned earlier, my ISP has assigned an IPv6 prefix with a subnet mask of /59 to me. This allows me to make 32 /64 subnets which is, apparently, the recommended subnet size for IPv6 (from what I have read so far at any rate). Two of these /64 subnets are already taken up by my FRITZ!Box (one for the LAN network and one for the guest LAN network) which still leaves me with *plenty* of subnets I could use for my webserver. Now I just needed to figure out how to assign a subnet to my OPNsense installation. + +## FRITZ!Box settings +The first thing I had to do was change a couple of settings in the FRITZ!Box itself. By default, even prefixes delegated to a device behind the FRITZ!Box would still go through the FRITZ!Box’ own firewall and, thus, actually accessing the devices in the delegated prefix from the Internet would not be possible. To change that, I had to go into the FRITZ!Box’ settings under Internet and then Freigaben and add a new entry, select my OPNsense and then toggle the button that reads Firewall für delegierte IPv6-Präfixe dieses Gerätes öffnen. (Open the firewall for prefixes delegated to this device). This should look as follows in the router’s web inteface: + +![A screenshot from the webinterface of my router showing how to enable opening the firewall for delegated prefixes of this device](/assets/images/blog_posts/hosting_at_home_p1/delegated_prefix_fritz.png) + +## OPNsense settings +After changing the settings in the FRITZ!Box, I logged in to my OPNsense installation and had to change a couple of things there. This part will probably be a bit longer as there are several steps involved. I had to change the settings of both my WAN and LAN inteface and also enable a few other things. + +### WAN interface +The first thing I had to do was go into Interfaces and then WAN and change the IPv6 Configuration Type to DHCPv6. Additionally, I had to set the Prefix delegation size (which I, in this case, just set to 60) and I also had to tick the box that said Send prefix hint. This should look as follows: + +![](/assets/images/blog_posts/hosting_at_home_p1/wan_interface.png) + +Afterwards, OPNsense should have received an IPv6 address in the already existing LAN network of the FRITZ!Box (which it did in my case) and we should now have the ability to delegate prefixes (16 of them in this case because of the /60 subnet) to our interfaces. To be honest, choosing such a large subnet delegation was probably a bit overkill as I will only be needing _one_ /64 subnet for my LAN interface so I’ll probably change that to something smaller at some point. + +### LAN interface +The next step involved actually assigning a prefix to the LAN interface. To do this, I had to go into Interfaces and then LAN this time. Here I set the IPv6 Configuration Type to Track Interface and once I did that, some more settings appeared at the bottom of the page titled Track IPv6 Interface. Here I selected a parent interface (which is the WAN interface) and assigned a prefix ID under Assign prefix ID. I just entered 1 here. Last but not least, I enabled the setting to allow manual configuration of DHCPv6 and Router Advertisements. This should look like this. + + +![](/assets/images/blog_posts/hosting_at_home_p1/lan_interface.png) + diff --git a/_posts/2024-10-29-hosting_at_home.md b/_posts/2024-10-29-hosting_at_home.md new file mode 100644 index 0000000..82dd120 --- /dev/null +++ b/_posts/2024-10-29-hosting_at_home.md @@ -0,0 +1,68 @@ +--- +layout: post +author: hexaitos +title: Hosting my websites at home but I only have a public IPv6 subnet +--- + +I wanted to write a small series of blog posts detailing how I made it so that my websites that are hosted at the server in my apartment (which only has a public IPv6 address) can be accessed from the Internet even if you’re in an IPv4-only network and I wanted to start by writing a post about how I delegated an IPv6 prefix to my OPNsense installation from my FRITZ!Box. (Un)fortunately, just as I finished writing it, I found out that the official (I think) [OPNsense documentation](https://docs.opnsense.org/manual/how-tos/ipv6_fb.html) has the _exact_ thing I wrote about documented already, so there’s really no point in my posting my own version that is almost literally the same thing. + +Therefore, I’ll just be skipping that portion of my blog post. If you’re in Germany and a customer of Vodafone’s, then you should have been assigned a /59 IPv6 subnet and you can quite simply follow the instructions on the official documentation that I linked above. + +Before I start this off, it is important to note that this will *only* work if you’re using Cloudflare’s proxy. I have not found any other DNS provider that allows you to do this, unfortunately. I know there are some who have quite strong (and often negative) opinions about Cloudflare, so if you’re one of those, then you will probably not be able to do this. If you’re not sure what I’m talking about, you should probably read up on Cloudflare and how their proxy functions first and try to form your own opinion on this matter. If you know of another (free!) way to do this _without_ using Cloudflare, then I’d be [happy to hear about it](/contact). + +_Also_, I’m not claiming that anything I’m about to explain is necessarily the best way of going about this; it’s simply what I found works quite well for me. If I wrote something that’s terrible advice or if you found something that I could improve, you are more than welcome to [contact me about that](/contact), too! + +And lastly, please note that a lot of ISPs do not technically allow the hosting of webservers if you only have a consumer contract and you might have to pay for a (usually more expensive) business contract instead. Or they might just straight up block certain ports from working in the first place on consumer contracts. Therefore, before you do anything, I urge you to check your ISP’s terms of service. + +With that out of the way, let’s get started! + +## Setup overview +Before we start, a quick rundown of my setup. I have a FRITZ!Box 6660 Cable (my main router) to which my server running Proxmox is connected. The FRITZ!Box gets a /59 IPv6 prefix but no public IPv4 (CGNAT). Running on the Proxmox host as a VM is an OPNsense installation. Its WAN network is connected to the *LAN* network of my FRITZ!Box (it, therefore, gets an IPv4 address in my FRITZ!Box’ LAN, `192.168.178.0/24`) and the OPNsense’s LAN network is a virtual network that all other VMs running on my Proxmox installation are connected to. Additionally, I have assigned a /64 IPv6 prefix to the LAN network of my OPNsense (see OPNsense documentation above) and all VMs get both a private IPv4 address (in the OPNsense’s `10.10.10.0/24` network) via DHCP and an IPv6 address either via SLAAC or DHCPv6. + +For my webserver in particular I made a separate and really small (/30) IPv4 subnet with a virtual IP in OPNsense, mostly so this public-facing LXC is in a different network from the VMs and LXCs that are _not_ open to the public. I’ll probably switch that over to a VLAN instead of a virtual IP soon. I feel like this is a bit overkill (and probably doesn’t add that much security anyway), but I wanted to do it anyway. However, this means that my webserver has a static IPv4 in a different network, namely `10.11.10.2/30` with `10.11.10.1/30` being the virtual IP I assigned to the OPNsense installation and it cannot talk to any other VM or LXC. + +I don’t want to share the exact IPv6 prefix I get from my ISP, but let’s just pretend it’s `2001:db8:0:e280::/59` where `2001:db8:0:e280::/64` is used by the FRITZ!Box itself and where `2001:db8:0:e291::/64` has been delegated to the OPNsense’s LAN interface. I have assigned a static IPv6 to the LXC which is running my webservers, namely `2001:db8:0:e280::1000:1/128`. + +My webserver is running Caddy and I’m using a module for Caddy called `dns.providers.cloudflare` so that Caddy can create an SSL certificate even when it’s behind Cloudflare’s proxy. + +Okay, that was probably quite a bit of information. The best tl;dr I can think of is: the public IPv6 my webserver gets is `2001:db8:0:e280::1000:1/128` (the prefix is not my actual prefix, this is just as an example). + +## Setting up Cloudflare +I’ll assume that you already are somewhat familiar with Cloudflare and how it works, especially after what I mentioned earlier in the blog post and I’ll also assume that you have already added your domain to Cloudflare. If you have not yet done so, please refer to [Cloudflare’s own documentation](https://developers.cloudflare.com/fundamentals/setup/manage-domains/add-site/) on how to do this. + +What you have to do is go into your domain’s DNS settings and create **only a single AAAA record with the proxy enabled**. Do not add another `AAAA` record or even an `A` record; simply add a `AAAA` pointing to the IPv6 address of your server. This should look as follows: + +![A screenshot from Cloudflare’s website showing a single AAAA record set for the domain bateleur.org](/assets/images/blog_posts/hosting_at_home/bateleur_org.png) + +This is probably the most important aspect of this entire thing if you want your website to be reachable even in networks that do not support IPv6. If you only set a `AAAA` record and no `A` record, Cloudflare will automatically translate requests from IPv4 networks so that your website can be reached even from those networks. + +You may also have to change the SSL settings of your domain. By default, the SSL setting is set to flexible which ended up not working for me and I had to set it to full instead: + +![A screenshot of Cloudflare’s SSL settings](/assets/images/blog_posts/hosting_at_home/cloudflare_ssl.png){:width="30%"} + +While you’re here, you might as well also create an API key either for your entire account or only for a particular zone / domain. For more information about what permissions need to be set, you can look at the [GitHub page for Caddy’s Cloudflare module](https://github.com/caddy-dns/cloudflare). + +## Firewall rules +The first thing you’d have to properly set up are the firewall rules, especially the WAN rules. Since the only thing running on my LXC that needs to be accessed from the Internet is a webserver, it only really needs to have ports `443` and maybe also port `80` open to the public. I created an [alias](https://docs.opnsense.org/manual/aliases.html) that includes both ports so that I don’t have to create _two_ rules and I simply named it `allowed_ports_default`. + +However, we can refine this rule a bit further: since _all the traffic_ going to our webserver should come from Cloudflare (as we’re using their proxy), you change the rule so that only traffic from Cloudflare’s network is accepted. + +To do this, you can simply create yet another alias that includes all the networks that Cloudflare uses. Luckily, Cloudflare publishes the list of their IPv6 subnets which you can find it here: [https://www.cloudflare.com/ips-v6/#](https://www.cloudflare.com/ips-v6/#). So all we need to do is create an alias that includes all seven (at the time of writing) subnets and put that alias into the Source field of our created WAN rules. The alias should end up looking as follows: + +![A screenshot showing a firewall alias containing all of Cloudflare’s IPv6 subnets](/assets/images/blog_posts/hosting_at_home/cloudflare_ips.png) + +And the rule should end up looking as follows: + +![A screenshot of an OPNsense rule](/assets/images/blog_posts/hosting_at_home/wan_rule.png) + +Additionally, you also have to set up the rules on the LAN interface. I created two LAN rules, one for the IPv6 and one for the IPv4 address of my webserver and I allowed only ports `443, 80, 123, 53` for both IPv4 TCP/UDP and IPv6 TCP/UDP. I also set up a LAN rule that blocks access from my webservers LAN network to all of my other LANs. + +## Caddy configuration +I’m assuming you know how to get a website up and running with Caddy. If not, I highly recommend looking at their [documentation](https://caddyserver.com/docs/), it’s really quite simple! + +However, getting Caddy to work with the Cloudflare DNS was a little bit annoying at first, because the Debian 12 LXC that I’m running did not have the newest version of Caddy in its repositories, apparently, and the version that was available did not have the `add-package` command which is needed to install the Cloudflare DNS module. So I simply downloaded the newest `.deb` file from Caddy’s GitHub, installed that and installed the Cloudflare DNS module using the command `sudo caddy add-package github.com/caddy-dns/cloudflare`. Afterwards, simply follow the instructions on their GitHub page on how to add the API key to your configuration. + +If you then restart Caddy after adding your configuration (or simply starting it for the first time), it should automatically generate an SSL certificate for you and your website should become reachable from _both_ IPv6- and IPv4-only networks. + +## Conclusion +Your website should now be accessible from the Internet! I hope you enjoyed reading this and I hope it will end up helping someone in the future. If you have any further questions, critique or whatever, [feel free to reach out to me](/contact). This is the first blog post I have written in a _long_ time, so if there’s anything you think could be improved in the next one, I would love to hear about it. \ No newline at end of file diff --git a/_site/2024/10/29/hosting_at_home.html b/_site/2024/10/29/hosting_at_home.html new file mode 100644 index 0000000..96ce95d --- /dev/null +++ b/_site/2024/10/29/hosting_at_home.html @@ -0,0 +1,96 @@ + + + + + + + +Hosting my websites at home but I only have a public IPv6 subnet + + + + + + +
+

Hosting my websites at home but I only have a public IPv6 subnet

+

This post was published on 29 Oct 2024

+ +

I wanted to write a small series of blog posts detailing how I made it so that my websites that are hosted at the server in my apartment (which only has a public IPv6 address) can be accessed from the Internet even if you’re in an IPv4-only network and I wanted to start by writing a post about how I delegated an IPv6 prefix to my OPNsense installation from my FRITZ!Box. (Un)fortunately, just as I finished writing it, I found out that the official (I think) OPNsense documentation has the exact thing I wrote about documented already, so there’s really no point in my posting my own version that is almost literally the same thing.

+ +

Therefore, I’ll just be skipping that portion of my blog post. If you’re in Germany and a customer of Vodafone’s, then you should have been assigned a /59 IPv6 subnet and you can quite simply follow the instructions on the official documentation that I linked above.

+ +

Before I start this off, it is important to note that this will only work if you’re using Cloudflare’s proxy. I have not found any other DNS provider that allows you to do this, unfortunately. I know there are some who have quite strong (and often negative) opinions about Cloudflare, so if you’re one of those, then you will probably not be able to do this. If you’re not sure what I’m talking about, you should probably read up on Cloudflare and how their proxy functions first and try to form your own opinion on this matter. If you know of another (free!) way to do this without using Cloudflare, then I’d be happy to hear about it.

+ +

Also, I’m not claiming that anything I’m about to explain is necessarily the best way of going about this; it’s simply what I found works quite well for me. If I wrote something that’s terrible advice or if you found something that I could improve, you are more than welcome to contact me about that, too!

+ +

And lastly, please note that a lot of ISPs do not technically allow the hosting of webservers if you only have a consumer contract and you might have to pay for a (usually more expensive) business contract instead. Or they might just straight up block certain ports from working in the first place on consumer contracts. Therefore, before you do anything, I urge you to check your ISP’s terms of service.

+ +

With that out of the way, let’s get started!

+ +

Setup overview

+

Before we start, a quick rundown of my setup. I have a FRITZ!Box 6660 Cable (my main router) to which my server running Proxmox is connected. The FRITZ!Box gets a /59 IPv6 prefix but no public IPv4 (CGNAT). Running on the Proxmox host as a VM is an OPNsense installation. Its WAN network is connected to the LAN network of my FRITZ!Box (it, therefore, gets an IPv4 address in my FRITZ!Box’ LAN, 192.168.178.0/24) and the OPNsense’s LAN network is a virtual network that all other VMs running on my Proxmox installation are connected to. Additionally, I have assigned a /64 IPv6 prefix to the LAN network of my OPNsense (see OPNsense documentation above) and all VMs get both a private IPv4 address (in the OPNsense’s 10.10.10.0/24 network) via DHCP and an IPv6 address either via SLAAC or DHCPv6.

+ +

For my webserver in particular I made a separate and really small (/30) IPv4 subnet with a virtual IP in OPNsense, mostly so this public-facing LXC is in a different network from the VMs and LXCs that are not open to the public. I’ll probably switch that over to a VLAN instead of a virtual IP soon. I feel like this is a bit overkill (and probably doesn’t add that much security anyway), but I wanted to do it anyway. However, this means that my webserver has a static IPv4 in a different network, namely 10.11.10.2/30 with 10.11.10.1/30 being the virtual IP I assigned to the OPNsense installation and it cannot talk to any other VM or LXC.

+ +

I don’t want to share the exact IPv6 prefix I get from my ISP, but let’s just pretend it’s 2001:db8:0:e280::/59 where 2001:db8:0:e280::/64 is used by the FRITZ!Box itself and where 2001:db8:0:e291::/64 has been delegated to the OPNsense’s LAN interface. I have assigned a static IPv6 to the LXC which is running my webservers, namely 2001:db8:0:e280::1000:1/128.

+ +

My webserver is running Caddy and I’m using a module for Caddy called dns.providers.cloudflare so that Caddy can create an SSL certificate even when it’s behind Cloudflare’s proxy.

+ +

Okay, that was probably quite a bit of information. The best tl;dr I can think of is: the public IPv6 my webserver gets is 2001:db8:0:e280::1000:1/128 (the prefix is not my actual prefix, this is just as an example).

+ +

Setting up Cloudflare

+

I’ll assume that you already are somewhat familiar with Cloudflare and how it works, especially after what I mentioned earlier in the blog post and I’ll also assume that you have already added your domain to Cloudflare. If you have not yet done so, please refer to Cloudflare’s own documentation on how to do this.

+ +

What you have to do is go into your domain’s DNS settings and create only a single AAAA record with the proxy enabled. Do not add another AAAA record or even an A record; simply add a AAAA pointing to the IPv6 address of your server. This should look as follows:

+ +

A screenshot from Cloudflare’s website showing a single AAAA record set for the domain bateleur.org

+ +

This is probably the most important aspect of this entire thing if you want your website to be reachable even in networks that do not support IPv6. If you only set a AAAA record and no A record, Cloudflare will automatically translate requests from IPv4 networks so that your website can be reached even from those networks.

+ +

You may also have to change the SSL settings of your domain. By default, the SSL setting is set to flexible which ended up not working for me and I had to set it to full instead:

+ +

A screenshot of Cloudflare’s SSL settings

+ +

While you’re here, you might as well also create an API key either for your entire account or only for a particular zone / domain. For more information about what permissions need to be set, you can look at the GitHub page for Caddy’s Cloudflare module.

+ +

Firewall rules

+

The first thing you’d have to properly set up are the firewall rules, especially the WAN rules. Since the only thing running on my LXC that needs to be accessed from the Internet is a webserver, it only really needs to have ports 443 and maybe also port 80 open to the public. I created an alias that includes both ports so that I don’t have to create two rules and I simply named it allowed_ports_default.

+ +

However, we can refine this rule a bit further: since all the traffic going to our webserver should come from Cloudflare (as we’re using their proxy), you change the rule so that only traffic from Cloudflare’s network is accepted.

+ +

To do this, you can simply create yet another alias that includes all the networks that Cloudflare uses. Luckily, Cloudflare publishes the list of their IPv6 subnets which you can find it here: https://www.cloudflare.com/ips-v6/#. So all we need to do is create an alias that includes all seven (at the time of writing) subnets and put that alias into the Source field of our created WAN rules. The alias should end up looking as follows:

+ +

A screenshot showing a firewall alias containing all of Cloudflare’s IPv6 subnets

+ +

And the rule should end up looking as follows:

+ +

A screenshot of an OPNsense rule

+ +

Additionally, you also have to set up the rules on the LAN interface. I created two LAN rules, one for the IPv6 and one for the IPv4 address of my webserver and I allowed only ports 443, 80, 123, 53 for both IPv4 TCP/UDP and IPv6 TCP/UDP. I also set up a LAN rule that blocks access from my webservers LAN network to all of my other LANs.

+ +

Caddy configuration

+

I’m assuming you know how to get a website up and running with Caddy. If not, I highly recommend looking at their documentation, it’s really quite simple!

+ +

However, getting Caddy to work with the Cloudflare DNS was a little bit annoying at first, because the Debian 12 LXC that I’m running did not have the newest version of Caddy in its repositories, apparently, and the version that was available did not have the add-package command which is needed to install the Cloudflare DNS module. So I simply downloaded the newest .deb file from Caddy’s GitHub, installed that and installed the Cloudflare DNS module using the command sudo caddy add-package github.com/caddy-dns/cloudflare. Afterwards, simply follow the instructions on their GitHub page on how to add the API key to your configuration.

+ +

If you then restart Caddy after adding your configuration (or simply starting it for the first time), it should automatically generate an SSL certificate for you and your website should become reachable from both IPv6- and IPv4-only networks.

+ +

Conclusion

+

Your website should now be accessible from the Internet! I hope you enjoyed reading this and I hope it will end up helping someone in the future. If you have any further questions, critique or whatever, feel free to reach out to me. This is the first blog post I have written in a long time, so if there’s anything you think could be improved in the next one, I would love to hear about it.

+ +
+ + + + diff --git a/_site/assets/css/styles.css b/_site/assets/css/styles.css index e9e7c1a..7809a74 100755 --- a/_site/assets/css/styles.css +++ b/_site/assets/css/styles.css @@ -332,6 +332,12 @@ div.desc { clear: both; } +code { + font-family: monospace; + background-color: lightgrey; + border: 1px grey; +} + @media (prefers-color-scheme: dark) { :root { --body-bg: rgb(49, 49, 49); diff --git a/_site/assets/images/blog_posts/hosting_at_home/bateleur_org.png b/_site/assets/images/blog_posts/hosting_at_home/bateleur_org.png new file mode 100644 index 0000000..f8a114d Binary files /dev/null and b/_site/assets/images/blog_posts/hosting_at_home/bateleur_org.png differ diff --git a/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ips.png b/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ips.png new file mode 100644 index 0000000..ea16626 Binary files /dev/null and b/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ips.png differ diff --git a/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ssl.png b/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ssl.png new file mode 100644 index 0000000..176c33c Binary files /dev/null and b/_site/assets/images/blog_posts/hosting_at_home/cloudflare_ssl.png differ diff --git a/_site/assets/images/blog_posts/hosting_at_home/wan_rule.png b/_site/assets/images/blog_posts/hosting_at_home/wan_rule.png new file mode 100644 index 0000000..e3c2e17 Binary files /dev/null and b/_site/assets/images/blog_posts/hosting_at_home/wan_rule.png differ diff --git a/_site/blog.html b/_site/blog.html index 6eb5b25..b5b7635 100755 --- a/_site/blog.html +++ b/_site/blog.html @@ -24,6 +24,12 @@