Specifying UDP Bind Address

Hi, I'm setting up Pi-Hole on fly.io.

For that, I'm using PiHole Docker.

It works really well - the web UI loads, and the DNS server works via TCP port 53 and DoT even (fly.io does the TLS termination.)

The only culprit is that in order to make it work in UDP port 53, the FTL needs to bind to the special fly-global-services:53 address. This is a fly.io specific detail - they do some eBPF voodoo for UDP routing.

Note that this is different from the INTERFACE envvar, and that the TCP server should keep listening on 0.0.0.0.

I tried to tinker around the source code and various config options, but I didn't find a way to change the UDP bind address.
Any ideas?

Thanks

Allowing public access to port 53 would mean you are running an open resolver, which poses a potential threat for all Internet users, e.g. by serving as a multiplier in a DNS Amplification attack .

The Pi-hole team strongly discourages Pi-hole’s usage as an open resolver, and we won't provide support in that case.

Hi Bucking_Horn, thanks for replying.
I get the concern, but keep in mind that I do pretty strict rate-limiting on the instance, so even in cases of attempted amplification attack, the bandwith my specific instance would be able to provide is absolutely miniscule.

Additionally, I'm limiting the accepted IP address to the specific (very small) country I'm living in, thus further reducing the attack surface.

Finally, the actual domain for my instance is a long random string (pi-SOMETHING-RANDOM-AND-LONG.fly.dev), making the changes for someone to actually hit it negligible.
The way that fly.io run their DDNS makes it impossible to do subdomain discovery, so someone will actually have to guess that domain.

All in all, although my instance is technically public, it shouldn't get used by anybody other than me.

IP addresses can be spoofed, and IP range port scans are not affected by domain names.

I appreciate the efforts you took to avoid exposure, but the recommended way to access a cloud-based Pi-hole is by means of a VPN.
You may refer to Guides|VPN from Pi-holes documentation for related suggestions for some VPN software packages.

Yeah, I know. The reason I don't want a VPN is because running VPN on Android is mutually exclusive if I want to use an actual VPN for something else.

That's correct (though it doesn't mean you can't manage multiple VPNs on Android - it's just that at most one of them can be active at a given time).
Is that an actual requirement, e.g. because you already have a VPN service provider, or more a sort of a hypothetical option?

You should be aware that it's not uncommon that VPN service providers may force DNS traffic to their own DNS servers, in an effort to avoid DNS leakages. Chances are you would not be able to use your Pi-hole for DNS with a VPN service provider anyway.
Based on your preferences and current connectivity, switching between your Pi-hole VPN and your VPN service provider may be an option.

That's fair enough, but configuring Pi-Hole as a public resolver without VPN is a lot "cleaner".

Given the security measures I've taken, would you like to help me out? :slight_smile:

It's undoubtedly easier, but this is not about your convenience - it's about keeping the risks at bay for all of us, including you.

I won't turn this topic into a guide for running an open resolver on fly.io.

Please consider shutting down your ports 53 and 80 to the public and use a VPN to manage access to your Pi-hole.

This is still an open resolver, just with a potentially smaller audience.

1 Like

Look, I totally get your point.

But this is no different from running any public web service, there's nothing special about Pi-Hole or even DNS.

Amplification attacks work because it's easy for an attacker to make a (DNS) server send large responses to small requests.

In principle, this can be done with any type of service - even HTTP GET to google.com returns a result which is much larger than the request.

(Yes, Google has some sophisticated bot protection in place - but a layperson's random personal site doesn't.)

Technically, UDP might be a bit more powerful "amplifier" since it's "cheap" for an attacker to generate a lot of outgoing DNS (UDP) requests since they are stateless, but still, in principle it should be roughly equivalent. My point is that any public-facing server can be abused in this way.

Basically, because of that, I don't thing there's something wrong in running a public resolver... even more so, since -

  • I limit the audience
  • I limit the bandwidth
  • the cloud provider I'm using probably also limits bandwidth on their side
  • As I said, it's pretty comparable to running any public-facing web service in terms of its potential use in amplification attacks

If I'm wrong here, please LMK. All in all I feel my setup is pretty reasonable.

No it cant.
HTTP or HTTPS is TCP and not UDP like for DNS.
With UDP its easy to spoof the source IP and thats why its also sometimes called an DNS reflection/amplification DDoS attack.

With TCP, such a reflection attack would not be possible because of the TCP handshaking that goes on which does not occur with UDP.

I ended up blocking UDP anyways, since I can do just fine with just DNS-over-TLS.

DoT needs the correct hostname to operate, so randomly hitting my instance's IP isn't enough (unless the attacker does reverse DNS query for each IP... but fly.io doesn't support it anyways from my tests. Their IPs don't have corresponding PTR records.)

So we're good.

Thanks folks.

1 Like

DoT eliminates the possibility of reflection/amplification since that attack is based on the capabilities, or actually lack of capabilities, of udp. DoT is a really good way to use Pi-hole when you're not on your home network.

One of the developers has a Gist for setting up traefik to do DoT at DoT.yml · GitHub if you need some hints. What front end are you using?

1 Like

Fly.io.

Doing DoT there is simple:

$ cat fly.toml
...
[[services]]
  internal_port = 53
  protocol = "tcp"

  # fly.io does TLS termination here
  [[services.ports]]
    handlers = ["tls"]
    port = 853

That's it.

Hmm, pretty simple. And they handle certificate generation and rolling on renewal?

Yep. You get a app-name.fly.dev domain. They handle certs with Let's Encrypt.
I can set up a custom domain and do more involved things, but it's not a requirement.

Fly.io is a high-level-abstraction cloud provider, somewhere in the middle between AWS EC2 and Lambda, if you will.

  • Apps are mostly stateless (although you can attach volumes and they do offer durable databases which, of course, are stateful)
  • You don't get a normal VM, like in EC2, but something more confined - it's a Firecracker "micro-VM". For example, you can't roll your own kernels.

So, as this type of cloud provider, I'd expect them to handle certs automagically, which they do :slight_smile:

1 Like

@DanSchaper I've published this setup on my Github, feel free to tinker with it.
https://github.com/matan129/fly-hole

1 Like