core icon indicating copy to clipboard operation
core copied to clipboard

Add MAP-T/MAP-E support

Open hitech95 opened this issue 4 years ago • 17 comments

Important notices

Before you add a new report, we ask you kindly to acknowledge the following:

  • [X] I have read the contributing guide lines at https://github.com/opnsense/core/blob/master/CONTRIBUTING.md
  • [X] I have searched the existing issues and I am convinced that mine is new.

Is your feature request related to a problem? Please describe.

No

Describe the solution you like

Please add MAP-T and other transitional technologies support as soon as possible.

Additional context

The depletion of IPv4 addresses is forcing many ISPs, especially new ones, to migrate to IPv6 networks while supporting IPv4 using transition mechanism built on IPv6 (IPv4aaS - IPv4 as a Service), like MAP-T, MAP-E, 464XLAT and others (see RFC8585). Fibre and FTTH-GPON deployments are accelerating this changes, as new ISPs are entering the market but can't source IPv4 blocks large enough, and IPv6 based transition technologies are more appealing than IPv4-based ones like a dual stack with CG-NAT.

In Europe, Sky Italia (Comcast owned) will switch using from a dual stack implementation used till now to a IPv6 + MAP-T network from August 2021. Melita (another ISP in EUROPE) is already using MAP-T. Looks like that Japan ISPs are heavily depending on MAP-T. Others may follow, especially local ISPs offering specific services for the SMB market.

Italy is a country where users have a right to use their own CPEs regardless of what the ISP provides - but the CPE must be able to comply with common standards used by the ISP network.

Right now there little to nothing CPEs capable to do so. The only open solution so far is Openwrt. Without MAP-T support, OPNsense won't be able to obtain a IPv4 address and access IPv4-only destinations.

hitech95 avatar May 11 '21 10:05 hitech95

This issue has been automatically timed-out (after 180 days of inactivity).

For more information about the policies for this repository, please read https://github.com/opnsense/core/blob/master/CONTRIBUTING.md for further details.

If someone wants to step up and work on this issue, just let us know, so we can reopen the issue and assign an owner to it.

OPNsense-bot avatar Nov 07 '21 10:11 OPNsense-bot

Even Iliad (Free) with the new internet offer via FTTH will also use the same protocols

luponata avatar Jan 31 '22 10:01 luponata

Any news on this issue? I would like to contribute but I don't even know where to start

GianlucaCesari avatar Aug 25 '22 08:08 GianlucaCesari

No news. pf.conf(5) holds a feature here:

     map-e-portset ⟨psid-offset⟩ / ⟨psid-len⟩ / ⟨psid⟩
           With nat rules, the map-e-portset option enables the source port
           translation of MAP-E (RFC 7597) Customer Edge.  In order to make
           the host act as a MAP-E Customer Edge, setting up a tunneling
           interface and pass rules for encapsulated packets are required in
           addition to the map-e-portset nat rule.

           For example:

                 nat on $gif_mape_if from $int_if:network to any \
                       -> $ipv4_mape_src map-e-portset 6/8/0x34

           sets PSID offset 6, PSID length 8, PSID 0x34.

I suppose it would have to be added to 1:1 rules?

The original ticket is a bit light on the requirements part. We can offer what pf(4) offers, but if that is enough here has not been established and how it should be configured from the GUI...

fichtner avatar Aug 25 '22 08:08 fichtner

Besides MAP-T/MAP-E support, it's not clear to me if "standard" ipip6 (i.e. with manual parameters instead of being provided by DHCPv6) is supported in opnsense...

psychowood avatar Sep 25 '22 15:09 psychowood

Looks like that Japan ISPs are heavily depending on MAP-T.

Let me share about the situation in Japan. I'm Japanese opnsense user and I reach here after much effort and unsuccessful attempts to connect with MAP-E. Japanese ISPs depend on MAP-E (RFC7597) or DS-lite (RFC6333). I think MAP-E seems to be more common.

As far as I know, some Japanese users who are building routers on FreeBSD or OpenBSD are using map-e-portset to connect. However, it's not simple and they face some problems.

https://qiita.com/yshdsnd/items/f8fb7ed136c19092b538 https://hoshizuki.hateblo.jp/entry/2022/08/05/065823 https://mano.xyz/post/2022-08-21-openbsd-map-e-pf/

I found someone patching the kernel to connect with MAP-E. Wow! https://mano.xyz/post/2021-12-30-openbsd-map-e/

ShuntaIto avatar Dec 21 '22 16:12 ShuntaIto

Is there anyway to implement this inside opnsense? https://github.com/toru-mano/openbsd-pf-map-e-ce

fuomag9 avatar Feb 11 '23 18:02 fuomag9

unlikely, best check man pf.conf if what you need is supported.

AdSchellevis avatar Feb 11 '23 18:02 AdSchellevis

I think Japan users (such as myself) are still interested in this. Seems someone got things working as needed for OpenWRT: https://github.com/fakemanhk/openwrt-jp-ipoe Maybe that could act as a guide for OPNsense? I haven't tried yet, but it sounds like the map-e-portset is sufficient, so long as appropriate NAT rules are specified as seen in the aforementioned pf.conf man page snippet.

schmitmd avatar May 19 '24 09:05 schmitmd

Well, same comment https://github.com/opnsense/core/issues/4983#issuecomment-1226926707 still applies, if someone wants to investigate how this can work on bsd, the starting point is implementing what's described in man pf.conf and open a ticket with the additions you need and how you tested them to be functional. Our ruleset is written to /tmp/rules.debug.

AdSchellevis avatar May 19 '24 09:05 AdSchellevis

I'll get testing!

schmitmd avatar May 19 '24 09:05 schmitmd

Been a while, but I finally got this working! All you really need is the following:

  1. The derived MAP-E information based on your assigned IPv6 prefix attained via DHCPv6. Plug the DHCPv6 info you receive on the WAN into this calculator and you'll get all the config variables you need. My examples below use 240b:10:2a40:9600::/64 as the input there (none of these are my actual IP values but they're valid).
  2. A virtual IP on your WAN defined as your CE (Customer Edge) IPv6 address. ex: 240b:10:2a40:9600:6a:482a:4000:9600. I imagine you could probably also get this set directly with your DHCPv6 client configuration by using the Advanced configuration mode on the WAN interface but I haven't drilled into that avenue too deeply yet.
  3. A GIF interface configured with an MTU of 1460 (1500 minus the 40-byte IPv6 header overhead, at least that's what's working for me) and:
  • Local Address: (The virtual IP defined on the WAN interface): 240b:10:2a40:9600:6a:482a:4000:9600 (this is the "Customer Edge" address)
  • Remote Address: The ISP's BR (Border Relay) IPv6 address: 2404:9200:225:100::64
  • Tunnel Local Address: 106.72.42.64 (this is the IP on your side through which you NAT traffic out)
  • Tunnel Remote Address: 106.72.42.64 (the target IP maintained by the ISP that you send packets out of on the other end of the tunnel. It's critical to note that it's the same IP on both ends) (again, at least for me, ymmv)
  • Tunnel netmask / prefix: 32 (I only tried with 32 but it's probably possible to set it to 15 as specified in option ip4prefixlen from the calculator).
  1. The NAT rule as defined in pf.conf(5). i.e.
nat log on gif0 inet from (ix1:network) to any tag map_e_egress -> 106.72.42.64 map-e-portset 4/8/150

(ix1:network is the LAN and the last three values are psid-offset/psid-len/psid)

It's item number 4 that needs code added into the OPNsense Firewall->NAT->Outbound options. I had to manually cram it into /tmp/rules.debug and pfctl -f /tmp/rules.debug, but it works!

schmitmd avatar Apr 20 '25 09:04 schmitmd

I'm an admin, not a developer, but I'm looking into where this stuff might be added in the code and if I get really really lucky, I'll try to put together a PR. I'd very much appreciate some help though if someone's got cycles as I expect the code I throw together to be pretty low-quality. 😞

schmitmd avatar Apr 20 '25 09:04 schmitmd

A couple other notes: since this tunnel is my only IPv4 egress, I had to set my Firewall->NAT->Outbound to Manual outbound NAT rule generation so that the automatic NAT rules don't clobber things up. I also had to tick Disable force gateway to get firewall's own IPv4 egress not to send junk to the MAP-E address without respecting the map-e-portset stuff. The first one is definitely a permanent need if you don't have any PPPoE IPv4 WAN setting (some Japan ISPs offer this in addition to MAP-E, some do not and it's generally congested/slow). The latter might be needed permanently, it might not; I haven't yet determined if that setting can be taught to respect the map-e NAT rule.

schmitmd avatar Apr 20 '25 09:04 schmitmd

so, do you think we can reopen this @AdSchellevis ? The official RFCs for MAP-E and MAP-T are here and here respectively. Sadly I know little to nothing about the delta between the two and have no environment in which I could test/make suggestions on MAP-T.

schmitmd avatar Apr 20 '25 09:04 schmitmd

@schmitmd I don't mind reopening, but this will need some effort from your end as well to make this happen. I can leave you some pointers to start with a PR, but it will likely also need some documentation and further testing.

AdSchellevis avatar Apr 20 '25 09:04 AdSchellevis

@schmitmd Given the legacy page contains almost all relevant settings (and the mvc one is currently incomplete), let's focus on the legacy page to inject this.

An input field in the old code is specified as:

https://github.com/opnsense/core/blob/7beec43db9273308e70c4c272fdcbaca0efa41bf/src/www/firewall_nat_out_edit.php#L797-L805

Which needs to be initialized:

https://github.com/opnsense/core/blob/7beec43db9273308e70c4c272fdcbaca0efa41bf/src/www/firewall_nat_out_edit.php#L99-L105

and stored:

https://github.com/opnsense/core/blob/7beec43db9273308e70c4c272fdcbaca0efa41bf/src/www/firewall_nat_out_edit.php#L225

A validation can be set in between.

As the 3 values fully belong to each other, we could consider only adding one property and do something smart around the validation. splitting it up is also a possibility, I'm just not sure that helps anyone (I don't have any experience with MAP-E)

As soon we have the value in our configuration, we need to dump it somewhere, when it's a single value, likely only needs a line around here:

https://github.com/opnsense/core/blob/7beec43db9273308e70c4c272fdcbaca0efa41bf/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php#L55

Happy coding! if you open a PR, we can discuss further steps.

AdSchellevis avatar Apr 20 '25 10:04 AdSchellevis

@schmitmd don't want to rush you, but as I haven't seen a PR yet, I thought to ask about progress. If you lost interest in working on this, we should probably drop the ticket back to the pool and close it.

AdSchellevis avatar Jul 08 '25 08:07 AdSchellevis

Tragically I haven't had the time to work on making a PR for this in any meaningful way, largely because I got side-tracked into trying to figure out why my PMTUD is having issues on MAP-E (ICMP doesn't work right, see below).

The map.sh.new from fakemanhk apparently makes ICMP echo requests work under OpenWRT (I guess through some conntrack black magic..?) but I've been having some trouble figuring out why pings don't work for me, even though it looks like it should..? To be fair, my C literacy isn't that great so I might just not be interpreting the PF code properly.

If I understand correctly, you can't really "SNAT" ICMP since it's not high-level enough to really apply like that (by virtue of not having/using actual ports). The fact is that I'm seeing ICMP echoreq packets properly go out through my MAP interface and yet nothing ever comes back on OPNsense where it does under OpenWRT (at least, with that custom map.sh.new script). It's possible this is simply some Japanese ISP idiosyncrasy but I don't think that's the case..

If someone with better C fluency can confirm my suspicion that map-e-portset is actually only applied if the protocol is TCP/UDP, that would confirm a couple theories I've got (and if that's the case, it'd be nice if it could be made to work, but that's way outside my capabilities).

edit: I looked through the PF code with fresh eyes and indeed I believe ICMP is excluded from map-e translation, likely due to the reason I mentioned (no actual ports to even be mapped, only IMCP IDs). Doing translation at that level would involve basically treating the IDs as if they were ports, and a bunch of non-RFC manipulation/tracking, which kind of explains why it's not already there (and why the custom script for OpenWRT is a thing). Even if someone made a working implementation, I doubt it'd be accepted upstream. 😿

schmitmd avatar Jul 13 '25 09:07 schmitmd

@schmitmd although I don't expect these nat rules only apply to tcp/udp, the documentation on the subject is very limited. I'm afraid someone has to invest quite some time to figure out a minimal viable product using map-e, which seems to be a bit unlikely to happen at the moment.

I'll drop this one back to the pool, if someone wants to have another shot at it, we can always reopen.

AdSchellevis avatar Jul 13 '25 11:07 AdSchellevis

This issue has been automatically timed-out (after 180 days of inactivity).

For more information about the policies for this repository, please read https://github.com/opnsense/core/blob/master/CONTRIBUTING.md for further details.

If someone wants to step up and work on this issue, just let us know, so we can reopen the issue and assign an owner to it.

OPNsense-bot avatar Jul 13 '25 12:07 OPNsense-bot