PurpleI2P / i2pd

🛡 I2P: End-to-End encrypted and anonymous Internet
https://i2pd.website
BSD 3-Clause "New" or "Revised" License
3.22k stars 415 forks source link

NAT46 support request #2002

Open bjtftw opened 8 months ago

bjtftw commented 8 months ago

How about adding support for NAT64 IP conversion directly to i2pd?

Right now I have moved to another ISP (LTE) which operates IPv6 single-stack network with 464xlat mechanism for IPv4 traffic, the problem is my Android 5.x phone (which acts as a WIFI AP for my entire home network) do support 464xlat and works great but have some issue with it and after 6 hours of working perfect this mechanism (probably clatd Android process) completely hangs (stops responding to any network requests), so I loss any IPv4 connectivity still having IPv4 addresses assigned to all the interfaces on my LAN machines and this means that this fault isn't easily visible to all the programs because they still try to use IPv4 connectivity as there are IPv4 addresses and default IPv4 route on the system and simply waits for connection timeout as they don't have any info that IPv4 connectivity is simply lost and shouldn't be used anymore.

This is why I have disabled IPv4 on my LAN machines completely and am using IPv6 only + DNS64 and it works great except for software like i2pd which doesn't use hostnames but uses direct IPs calls to make connections and in this case having NAT64 translation mechanism built into i2pd would help to get connectivity to IPv4 hosts by converting their IPv4 addresses to the form of NAT64PREFIX::IPv:4HEX internally.

As NAT64 is stateless it doesn't require too much code to be written it's just a conversion from IPv4 to NAT64 IPv6.

It would make sense to add additional config options to i2pd.conf like: nat64 = 1 nat64prefix = 64:ff9b::/96 so it would be possible to enable or disable this functionality and probably it would make sense to have it disabled by default.

General logic would be simple, if nat64=1 then we simply ignore all the IPv4 related system settings and don't even try to use IPv4 stack at all (even if we have interfaces with IPv4 addresses on them and default IPv4 gateway in the system) but we convert any IPv4 address to the form NAT64PREFIX::IPv:4HEX and use that instead.

orignal commented 8 months ago

We exclude it here https://github.com/PurpleI2P/i2pd/blob/openssl/libi2pd/util.cpp#L668 I think even we use it, we shouldn't publish such addresses

bjtftw commented 8 months ago

Yes, you definitely want to block publishing 64:ff9b::/96 IPs in router info as they are routable only within ISP network with NAT64 functionality but these addresses are still legit to use within IPv6 NAT64 network and shouldn't be abandoned completely as this is proper way of handling IPv4 traffic in IPv6 only networks with NAT64 functionality.

What I'm proposing is to add i2pd functionality that generates such IPv6 addresses for IPv4 only peers when on IPv6 only network with NAT64 support (which may be hard to autodetect so manual setting in i2pd.conf is the easiest way, the user should know if it needs it nat64 = true).

The only thing i2pd code have to do is to generate this 'fake' IPv6 address for every "IPv4 only" peer (only when nat64 = true is set by user as most users don't need this!) and use it for making connections.

Generation in reality means just adding NAT64PREFIX to the IPv4 address of peer like 1.2.3.4 -> 64:ff9b::1.2.3.4 or even better with HEX representation of IPv4 -> 64:ff9b::102:304 and using this to make connection, this way IPv6 only host can connect to IPv4 only peer.

That's all the story. We are fooling i2pd that IPv4 only host do have IPv6 address so i2pd can use it to make connection. Such a 64:ff9b::/96 address should be treated as normal IPv6 by i2pd only it's publishing should be avoided. The other part of translating it back to IPv4 and create connection to this IPv4 is on the NAT64 gateway side but i2pd don't need to worry about at all as it transparent.

agowa commented 6 months ago

Technically NAT64 could be (and once implemented preferably should default to) auto detecting. All it takes is a AAAA lookup for ipv4only.arpa. Being able to explicitly provide NAT64 settings could allow for traffic engineering but probably wouldn't be the common/expected case.

Also don't forget about the reverse NAT46 (technically also "just" NAT64, but different usage) which is often used within data centers to provide "IPv4aaS", I.E. to NAT IPv4 INBOUND traffic towards a specific IPv6 address (and sometimes with multiple layers of routing and maybe even WAN in between it and the server that binds it) often with a custom (sub-netted) prefix (I.E. it will be out of either a GUA or a ULA address depending on environment). For all i2pd cares about it would have to support multi homing on IPv6, as all IPv4 connections will appear as if they're from IPv6 endpoints on that "special address" (ok, technically it's just another normal IPv6 address to us, most of the lifting is in the translation happening elsewhere). A good way to think off this is using source routing, one of the IPv6 addresses on the interface on the server will be source routed through the infrastructure towards a NAT64/NAT46 gateway that holds the associated public IPv4 and does the translation (most common is 1:1 or with specific ports, where the port is often also encoded within the IPv6 address). (This is basically also similar to CGNATs with port-forwarding support [see e.g. RFC6888, RFC7599, and RFC7597], just without the 2nd layer of translation to keep the internal network IPv6-only)

DNS response for ipv4only.arpa

without NAT64

Server:         ::1
Address:        [::1]:53

Name:   ipv4only.arpa
Address: 192.0.0.171
Name:   ipv4only.arpa
Address: 192.0.0.170

with NAT64

Server:         ::1
Address:        [::1]:53

Name:   ipv4only.arpa
Address: 192.0.0.171
Name:   ipv4only.arpa
Address: 192.0.0.170

Name:   ipv4only.arpa
Address: 64:ff9b::c000:aa
Name:   ipv4only.arpa
Address: 64:ff9b::c000:ab
bjtftw commented 1 month ago

DNS response for ipv4only.arpa

This won't work in few specific scenarios:

  1. where user have changed it's DNS servers to some without DNS64 support then asking for ipv4only.arpa won't give NAT64 prefix and you have false negative response there

  2. when there is some specific mis-/configuration in ISP network as it is in mine, where on some smartphones models ISP sends addresses for regular DNS servers instead of DNS64 ones so this detection model won't work as in 1.

  3. if you have NAT64 functionality in your ISP network then in most cases you have 464xlat enabled on router/smartphone which means that LAN machines have regular IPv4 addresses (via DHCP on LAN side of the router) so we don't need proposed by me functionality enabled here as we already have IPv4 connectivity but ipv4only.arpa test would give a NAT64 prefix and i2pd would generate NAT64 equivalents of IPv4 addresses even we don't need them

So I think manual activation is still a good scenario, until i2pd devs want to really have it, than I can help in pointing how to implement this (on logic not a code level)

agowa commented 1 month ago

DNS response for ipv4only.arpa

This won't work in few specific scenarios:

  1. where user have changed it's DNS servers to some without DNS64 support then asking for ipv4only.arpa won't give NAT64 prefix and you have false negative response there

Not our problem this is a configuration error. If we're nice we could force a lookup using the on-link dns server (at least with systemd-resolved), however that may be unexpected in other cases . I'd say this intentional manual change by a user would be a configuration error and it is the responsibility of the user to provide a DNS64 server that matches the NAT64 of the network...

  1. when there is some specific mis-/configuration in ISP network as it is in mine, where on some smartphones models ISP sends addresses for regular DNS servers instead of DNS64 ones so this detection model won't work as in 1.

Also configuration error, at most we can implement multi-homing and happy eyeballs. But everything else is out of scope for us anyway. And just having these two would already allow to function (even though in a degraded state).

  1. if you have NAT64 functionality in your ISP network then in most cases you have 464xlat enabled on router/smartphone which means that LAN machines have regular IPv4 addresses (via DHCP on LAN side of the router) so we don't need proposed by me functionality enabled here as we already have IPv4 connectivity but ipv4only.arpa test would give a NAT64 prefix and i2pd would generate NAT64 equivalents of IPv4 addresses even we don't need them

Not necessarily, also there are not just public ISPs, and data center networks are also relevent to i2pd, so a pure IPv6 only network is still not that uncommon...

So I think manual activation is still a good scenario, until i2pd devs want to really have it, than I can help in pointing how to implement this (on logic not a code level)

why? So instead of opting for something that enables connectivity in some more cases you opt to break it in all cases instead?

bjtftw commented 1 month ago

why? So instead of opting for something that enables connectivity in some more cases you opt to break it in all cases instead?

Well it's just my opinion, let ON+AUTODETECT be the default, but still I think user should have config option to force this ON/OFF despite of autodetecting result as I showed you some scenarios where autodetecting won't work and even if these are user/ISP config errors having this option would help to overcome those errors with it. I think all autodetect mechanisms should have option to be manually controlled as we don't know any possible scenario.

agowa commented 1 month ago

Nothing against explicit overwrites. Some people have especially cursed and broken environments and being able to disable autodetect is always good for debugging, even though when it turns out to have been unrelated.