Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for draft-ietf-sunset4-nat64-port-allocation #175

Open
ydahhrk opened this issue Sep 30, 2015 · 6 comments
Open

Add support for draft-ietf-sunset4-nat64-port-allocation #175

ydahhrk opened this issue Sep 30, 2015 · 6 comments
Labels
New feature Status: Coded Needs testing and release

Comments

@ydahhrk
Copy link
Member

ydahhrk commented Sep 30, 2015

2018-11-25 Update

Hello. If you came here from the survey, you'll notice that this thread used to be a pretty lousy introduction to the feature. So I'll try again:

I think it's best explained through an example:

Suppose that your NAT64 has 5 IPv6 customers (Where "customer" is either an IPv6 address or a block of IPv6 addresses assigned to someone) and your pool4 has 1000 transport addresses.

Currently, Jool assigns those transport addresses on demand. For example, if customer A requests one transport address, Jool will give it one transport address. If customer B requests the remaining 999 addresses, Jool will give it the remaining 999 addresses. And customers C, D and E will get nothing.

Greedy customers can be currently addressed through the use of mark, but this loses convenience as your customer pool grows.

So the idea is that you will be able to tell your NAT64 something along the lines of "automatically divide the pool4 into 5 blocks, and assign them evenly to each of my customers."

Because this will also make your transport address assignments predictable, it will also free you from the need of BIB logging.

Progress: A first iteration of this feature has already been coded, and can be found in the issue175 branch. It's missing documentation, a (likely arduous) merge and some testing.

Original post

This is the draft as of now. It's mostly added flexibility to pool4.

Stuff I find particularly attractive:

  • Utter randomization of pool4 port selection ("to enhance the defense against hijacking of flows").
  • Per-customer or per-block granularity (Prevent one single client or block of clients from hogging up the entire pool4 - also minimize BIB and session logging).
  • Add support for MAP-T (which should perhaps be considered a separate issue). Implement MAP-T? #193

Supporting these is valuable even if the draft doesn't reach RFC status.

This will take a while. It's definitely post-issue-140 material.

@ydahhrk ydahhrk added this to the 4.1.0 milestone Sep 30, 2015
@ydahhrk
Copy link
Member Author

ydahhrk commented Nov 18, 2015

This is assigned to both @frutos93 and @ddnov89. (Github doesn't support multiple assignees.)

@toreanderson
Copy link
Contributor

I wasn't sure to leave this comment in this issue or in #114 but here goes...

Accessing IPv4 FTP servers through Jool generally works fine, provided that the server supports the EPSV command. However, there is one gotcha: Some (most?) FTP servers require that the data connection come from the same client source IP address as the control connection. That breaks if Jool is configured with an IPv4 pool containing more than a single address, as Jool may then pick a different IPv4 transport address for the client's FTP data connection, which will be rejected by the IPv4 FTP server.

Jool could help work around this problem by ensuring that individual sessions originating from a single IPv6 client address is always assigned the same IPv4 transport address (to the extent possible - it could of course be that the IPv4 transport address in question is fully utilised, in which case it is preferable to fall back on another available IPv4 transport address rather than failing to set up the binding/session).

@ydahhrk
Copy link
Member Author

ydahhrk commented Dec 8, 2015

Jool could help work around this problem by ensuring that individual sessions originating from a single IPv6 client address is always assigned the same IPv4 transport address

BTW, Jool 3.3 tries very hard to do this. (If the newer features aren't an issue, maybe a downgrade isn't so bad.)

It's one of the RFC 6146 pool4 requirements I had to discard from Jool 3.4 because it's very anti-RFC6056-y:

Address preservation, as well as parity/range port preservation were not considered in this iteration (and there's uncertainty on whether they will return in the future) due to the potential performance impact and the newer RFCs' complete disregard of them.

(6056 is a lot friendlier to 7422 and draft-ietf-sunset4-nat64-port-allocation than original NAT64 (6146).)

("Address preservation" is when the NAT64 tries to mask all packets from the same IPv6 node using the same IPv4 address. I think I came up with that expression.)

That said, making the 6056 algorithm work as you want doesn't sound too hard. Maybe we could turn it into a configuration switch, even.

Here goes nothing:

RFC 6056 (or, more specifically, algorithm 3 of RFC 6056) defines a means to find a transport address which is reasonably random and dependant of several original packet fields. This transport address is then used as the source of the translated packet. The fields included in the equation are

  • Source address
  • Destination address
  • Destination port

The rationale, I think, is that all packets that share those values will yield adjacent translated source transport addresses (well, they will yield the same translated source transport address. But BIB will tweak the ports a little since they aren't allowed to collide). This is a form of "attempted" address preservation in that packets that share source address and destination do tend to be sourced similarly, but it doesn't guarantee the pool4 address completely runs out of ports before moving on to the next one. Still, it's clever and does what it wants well.

If "Destination port" wasn't part of that list, your EPSVs would work much more reliably, right?

So maybe we should let the operator decide which fields should be present in the equation. We could even throw Source port to that list for shits and giggles (and disable it by default).

So you would remove Destination port and cope with the increased binding collision due to internal nodes sometimes talking to the same external nodes.

It would be easy to implement. Would it be worth the performance hit, though?

@toreanderson
Copy link
Contributor

If "Destination port" wasn't part of that list, your EPSVs would work much more reliably, right?

Exactly. The destination port of the FTP data connection is picked randomly by the server on-demand. Ensuring FTP to EPSV-capable servers works would be worth the performance hit for me.

@pierky
Copy link
Contributor

pierky commented Apr 21, 2016

I run some tests using an old server (2 x 3.00 Intel Xeon, 800 Mhz bus, 2 MB L2 cache) to evaluate the impact of a lot of ip6tables -t mangle ... --set-mark x and jool --pool4 --add ... --mark x statements.

The goal was to leverage the (great) feature introduced with #115 to obtain a deterministic mapping between IPv6 source addresses and IPv4 addresses and ports used in NAT64 (you know, to avoid heavy logging).

So, I used iperf in TCP single connection mode to send traffic from the IPv6 host (100 Mbps NIC) toward an IPv4-only host (100 Mbps NIC) via the Jool box.

  • Test n. 1: 1500 ip6tables rules + 1500 jool --pool4 --add statements = 46.2 Mbps.
  • Test n. 2: 1500 ip6tables rules + a single jool --pool4 --add statement (with the --mark matching the source IPv6 prefix) = 90.5 Mbps.
  • Test n. 3: no ip6tables rules and only a single jool --pool4 --add (with no --mark) = 91.2 Mbps.

I know these tests have rough edges (I'll continue to work on them), but do you think these numbers make sense? It seems that the bottleneck is in the Jool's lookup mechanism more than ip6tables. If so, do you think implementing RFC7422 deterministic algorithms may lower this bottleneck?

@ydahhrk
Copy link
Member Author

ydahhrk commented Apr 21, 2016

Those results make sense.

Each translation involves pool4 lookups, which are implemented as an ugly sequential search. From what I can remember, this is because other requirements prevent pool4 from being stored sorted in any way. (But I should probably take another peek since it sounds quite unreasonable.)

You are correct; implementing RFC7422 deterministic algorithms will lower this bottleneck, because it converts a lot of the algorithm complexity to straightforward address arithmetic.

I forgot to mention this feature is being worked on here, but is rather far from completion still. RFC7422 is part of what draft-ietf-sunset4-nat64-port-allocation wants.

dhfelix referenced this issue Jan 18, 2018
This commit implements recommendations from the rfc 7422 
and the draft sunset4-nat64-port-allocation.
@ydahhrk ydahhrk removed this from the 4.1.0 milestone Jan 9, 2019
@ydahhrk ydahhrk added the Status: Coded Needs testing and release label Aug 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New feature Status: Coded Needs testing and release
Projects
None yet
Development

No branches or pull requests

5 participants