firezone / firezone

Enterprise-ready zero-trust access platform built on WireGuard®.
https://www.firezone.dev
Apache License 2.0
6.78k stars 283 forks source link

Gateway does not NAT to loopback IPs #5775

Closed jamilbk closed 3 months ago

jamilbk commented 3 months ago

This is preventing customers from defining the host the Gateway is deployed on as a Resource in order to access it.

Refs #5773

jamilbk commented 3 months ago

I've verfified that the Gateway is able to successfully resolve its hostname to 127.0.0.1 -- the problem seems to be at some point later, likely with NAT?

This was working prior to Gateway 1.1 as I was using it to demo connectivity to Gateway container on sales calls.

jamilbk commented 3 months ago

Steps to reproduce:

  1. Define a DNS Resource with address = Gateway's hostname
  2. Try to ping
  3. Notice it times out

This is for a system-deployed Gateway, but also plain vanilla binary exhibits the issue as well.

jamilbk commented 3 months ago

I've verified this does work for local interface IPs on two different interfaces. Just not the loopback.

jamilbk commented 3 months ago

This was working prior to Gateway 1.1 as I was using it to demo connectivity to Gateway container on sales calls.

Scratch that -- I was using one of the interface addresses for the above. I can confirm this issue also happens with:

ping -I tun-firezone 127.0.0.1

so the issue is probably that we're past the point in the netstack where we can insert packets destined for the loopback address.

thomaseizinger commented 3 months ago

This was working prior to Gateway 1.1 as I was using it to demo connectivity to Gateway container on sales calls.

Scratch that -- I was using one of the interface addresses for the above. I can confirm this issue also happens with:

ping -I tun-firezone 127.0.0.1

so the issue is probably that we're past the point in the netstack where we can insert packets destined for the loopback address.

If you active wire::dev=trace, do you see those ICMP packets coming in? We could respond to ICMP but I am not sure there is much other stuff we can meaningfully do?

jamilbk commented 3 months ago

I see them going out the NAT but no reply. I don't think it's possible for external interface types like tun and ethernet to send traffic to loopback interfaces.

thomaseizinger commented 3 months ago

I see them going out the NAT but no reply. I don't think it's possible for external interface types like tun and ethernet to send traffic to loopback interfaces.

From connlib's perspective an ICMP you send to the TUN interface is an "incoming" packet (we read from the TUN device). We have to generate the ICMP reply and send it back if we want loopback IPs to work, I believe.

We can do that for ICMP, it is not a difficult protocol. Not sure if it is worth it? Could be used a simple liveness check of connlib?

jamilbk commented 3 months ago

But it's not going to the TUN interface, it's going to the lo interface. So we:

  1. read from the TUN device
  2. see the ICMP packet
  3. establish the nat peer table entry with SRC as the tun interface IP and DEST as 127.0.0.1
  4. send it off
  5. fail, the netstack won't honor this because 127.0.0.1 is not routable.

We'd probably have to rewrite the src to 0.0.0.0 or something, and then perform the reverse mangling when we receive the reply, right? Not sure it's worth all the hassle to be able to ping 127.0.0.1 remotely.

jamilbk commented 3 months ago

Or we'd need some special case to check for loopback IPs and make sure they get sent and received out the lo interface.