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 BIB entries with dynamic IPv4 addresses #304

Open
tiagogaspar8 opened this issue Nov 6, 2019 · 30 comments
Open

Add support for BIB entries with dynamic IPv4 addresses #304

tiagogaspar8 opened this issue Nov 6, 2019 · 30 comments
Labels
New feature Status: Stuck Development paused due to unavailable external input

Comments

@tiagogaspar8
Copy link

Hey Everyone!

It's just a suggestion but could we add a way to configure jool from a file, using uci or some other type of file configuration?

Thanks!

@ydahhrk
Copy link
Member

ydahhrk commented Nov 6, 2019

Are you aware of this?

@tiagogaspar8
Copy link
Author

No I wasn't!
I thought I had read all the documentation but I guess I was wrong.
I'd like to add a default startup script to OpenWRT but for that I needed Jool to have a default configuration file. I'll be trying to do that. Just one question off topic, How do I do a type of "port forwarding"? I've seen the bib static entries but those require me to enter a ipv4 address and my wan has a dynamic IP address.

@ydahhrk
Copy link
Member

ydahhrk commented Nov 8, 2019

It cannot be done as currently implemented, but if it's a legitimate use case I could add support for it.

But how are you expecting port forwarding to work? If your IPv4 address changes constantly, how is your IPv4 client supposed to know it?

@ydahhrk
Copy link
Member

ydahhrk commented Nov 8, 2019

I'd like to add a default startup script to OpenWRT but for that I needed Jool to have a default configuration file.

By the way: I'm not entirely sure, but from a quick Google search it seems OpenWRT uses init.d. We already have init scripts for Jool, in case you want to reuse them:

(They might need some adjustments, such as binary paths)

@tiagogaspar8
Copy link
Author

For the outside connection I use a dynamic DNS, so clients never lose access.
So for example if I want to connect to a server on my LAN from the external IPv4 WAN address I'd do:

client on WAN-IP4 - - - - - - > WAN-IP4:443 - - - - - - >SERVER-IP6:443
                 (connects to)              (forwards to)

As for the scripts you provided, they use some functions I really have no idea of what they are like for example . /lib/lsb/init-functions witch doesn't exist in OpenWRT. Also there are som sections of the script that I don't understand what they do like check_permissions(if this is to check if the software running the script has enough privileges to execute the needed commands OpenWRT doesn't need it), also I believe the check_workspace isn't also needed since upon install OpenWRT adds the config file and the binaries, so at least the section for checking the existence of the program are not needed.
If you want I can show you the files I made and you can give me some help, what do you think?

@ydahhrk
Copy link
Member

ydahhrk commented Nov 12, 2019

check_permissions(), check_workspace() and probably others exist for the sake of Linux Standard Base (LSB) conformance. For example, check_permissions() ensures that the script returns 4 on "user had insufficient privilege", and not something else. LSB conformance was required by Debian, but it's possible OpenWRT might not care about it.

For the outside connection I use a dynamic DNS, so clients never lose access.

Ok, but just to understand this a little better: Are these connections supposed to survive the address change? Do the clients open new connections when the address changes? Or do these clients somehow modify their socket addresses so as to avoid repeating the TCP handshake?

@tiagogaspar8
Copy link
Author

LSB conformance was required by Debian, but it's possible OpenWRT might not care about it.

OpenWRT just need to have the commands necessary to the start of the package, if it can check some stuff before starting, ok, but it's not mandatory. I'm going to be pushing it to a temporary branch in my forked packages repository, check it out if you want! 😄

Ok, but just to understand this a little better: Are these connections supposed to survive the address change? Do the clients open new connections when the address changes? Or do these clients somehow modify their socket addresses so as to avoid repeating the TCP handshake?

You're asking hard questions, I want my server to serve a nextcloud instance to the outside, it's rarely going to be used, but I belive OpenWRT would keep the connection open even after the IP changed, so if the address changes the client would continue to communicate with the new address (?) I believe at least.

@ydahhrk
Copy link
Member

ydahhrk commented Nov 13, 2019

I want my server to serve a nextcloud instance to the outside, it's rarely going to be used, but I belive OpenWRT would keep the connection open even after the IP changed, so if the address changes the client would continue to communicate with the new address (?) I believe at least.

As far as I know, a connection (whether TCP or UDP) is invariably identified by its IP addresses and ports. If you change one address, then the connection breaks and needs to be re-established from scratch. (Unless I'm missing some strange hack.)

And if that's what you expect to happen, then I think it would be most elegant if the dynamic DNS informed Jool of the new address every time it's changed (by updating the BIB and perhaps pool4 as well). I mean Jool could theoretically monitor the address and respond appropriately whenever it changes, but I feel like this wouldn't be optimal or terribly reliable.

What do you think?

@ydahhrk ydahhrk added the Discussion Not a bug (for now) label Nov 20, 2019
@tiagogaspar8
Copy link
Author

I see what you mean, sorry for the delay answering but shchool's been hard ahaha.
I don't think there's any need for it, jool can automatically obtain the IP address from the linux routing table or from the interface's IP address. I believe you're right TCP and UDP would break connection but there's no problem for three reasons:
1st - TCP will break the connection when the timeout is reached even if the IP doesn't change so there's no issue there.
2nd - UDP bindings aren't reliable, they're not suitable for connections that need a reliable strem so there's no issue there either.
3rd - HTTP will soon be moving towards HTTP/3 and this one is a protocol (QUIC) that predicts and adapts to changes in the IP address.

So for me, there just needs to be a simple port-forwarding system that redirects connections coming form the WAN address to some specified LAN address.

Also, on another note, what do you think of this? Did I do it right?
tiagogaspar8/packages@baec517

@ydahhrk
Copy link
Member

ydahhrk commented Nov 29, 2019

Ok. My prediction is that this will look something like

jool bib add 2001:db8::1#1080 *#1080

I can't think of any problems with this idea (other than what I expect is going to be a horrifyingly messy implementation) but I'll keep thinking.

Also, on another note, what do you think of this? Did I do it right?

Your sample configuration files are going to create a lot of problems for careless users who trust their defaults to be reasonable. I don't think anyone should enable logging-session (it's a pointless and dumb configuration field and I'm planning to remove it at some point), and your mtu-plateaus might cause some of your clients to think they need to create impossibly small packets (sized 6, in fact. Not even enough for an IPv4 header). People should definitely not enable ss-enabled willy-nilly because it's not performance-friendly, and your f-args is optimized for certain poorly-designed application protocols and nothing else.

If you want to include every configuration option for the sake of easy modification it's fine, but you should probably use Jool's default values instead of random ones.

@ydahhrk ydahhrk added New feature Status: Not Started Progress is 0% and removed Discussion Not a bug (for now) labels Nov 29, 2019
@ydahhrk ydahhrk changed the title Add OpenWRT uci support or some other form of config file Add support for BIB entries with dynamic IPv4 addresses Nov 29, 2019
@tiagogaspar8
Copy link
Author

I can't think of any problems with this idea (other than what I expect is going to be a horrifyingly messy implementation) but I'll keep thinking.

That seems about right
If you need any help just summon me and I'll be here when I can.

If you want to include every configuration option for the sake of easy modification it's fine, but you should probably use Jool's default values instead of random ones.

I can just add default configuration files all commented out and let people fill it. What do you think?

@ydahhrk
Copy link
Member

ydahhrk commented Dec 19, 2019

I can just add default configuration files all commented out and let people fill it. What do you think?

Agreed.

@tiagogaspar8
Copy link
Author

Ok, I'll get to it. Where can I get the default configuration files?

@ydahhrk
Copy link
Member

ydahhrk commented Dec 24, 2019 via email

@tiagogaspar8
Copy link
Author

Oh god.
I'll do it as soon as I can.

@tiagogaspar8
Copy link
Author

Well after a bit of research, JSON doesn't support comments, so I have decided to switch the "manually-enabled" option to enabled, that way jool won't start unless this is set to disabled, right?
Sorry for the long delay.

@ydahhrk
Copy link
Member

ydahhrk commented Jan 8, 2020

"comment" tags are specified to be ignored by Jool's interpreter in any context.

You can therefore group sample fields in comment tags, and Jool should ignore them:

"global": {
	"comment": {
		"pool6": "64:ff9b::/96",
		"manually-enabled": false,
		"zeroize-traffic-class": true,
		"override-tos": false,
		"tos": 254,
		"mtu-plateaus": [1, 2, 3, 4, 5, 6],
		"amend-udp-checksum-zero": true,
		"eam-hairpin-mode": "simple",
		"randomize-rfc6791-addresses": false,
		"rfc6791v6-prefix": null,
		"rfc6791v4-prefix": null
	}
},

(Disclaimer: Untested, but you should get the general idea.)

@ydahhrk
Copy link
Member

ydahhrk commented Jan 8, 2020

(Although, for the record, I still think you should include sensible default values. "manually-enabled": true is certainly sensible.)

@tiagogaspar8
Copy link
Author

I think that if "manually-enabled" makes jool not start it is the best way to not screw things up while leaving the configuration files clean and "simple", right? If you agree with me as soon as I'm ready I'll show you the final commit

@ydahhrk
Copy link
Member

ydahhrk commented Jan 8, 2020

Hmm... I think there's some sort of language barrier getting in the way of our conversation.

I will try to be as clear as I can:

manually-enabled is a configuration option that behaves like this:

  • "manually-enabled": true: Jool translates.
  • "manually-enabled": false: Jool does nothing.

My opinion is that manually-enabled should be true by default. This is because we don't want to add unnecessary steps to Jool's starting procedure. If translators instances are disabled by default, new users would struggle to enable them.

As currently implemented, manually-enabled is in fact true if you omit it. manually-enabled is not false by default. Jool is automatically enabled by default.

Therefore, you don't need to include manually-enabled in the sample configuration, unless you're trying to list every available configuration option for the sake of being as explicit as possible.

And if you do want to list every configuration option, my opinion is that you should not change the default values, because their current defaults make the most sense in the vast majority of production environments.

Therefore, my opinion is that you should include the following global defaults for NAT64:

"global": {
	"manually-enabled": true,
	"pool6": "64:ff9b::/96",
	"zeroize-traffic-class": false,
	"override-tos": false,
	"tos": 0,
	"mtu-plateaus": [65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, 68],
	"address-dependent-filtering": false,
	"drop-icmpv6-info": false,
	"drop-externally-initiated-tcp": false,
	"udp-timeout": "5:00",
	"tcp-est-timeout": "1:00",
	"tcp-trans-timeout": "2:00:00",
	"icmp-timeout": "4:00",
	"maximum-simultaneous-opens": 10,
	"source-icmpv6-errors-better": true,
	"f-args": 11,
	"handle-rst-during-fin-rcv": false,
	"logging-bib": false,
	"logging-session": false,
	"ss-enabled": false,
	"ss-flush-asap": true,
	"ss-flush-deadline": 2000,
	"ss-capacity": 512,
	"ss-max-payload": 1452
},

and the following global defaults for SIIT:

"global": {
	"manually-enabled": true,
	"comment": "Please change pool6 according to your needs!",
	"pool6": null,
	"zeroize-traffic-class": false,
	"override-tos": false,
	"tos": 0,
	"mtu-plateaus": [65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, 68],
	"amend-udp-checksum-zero": false,
	"eam-hairpin-mode": "intrinsic",
	"randomize-rfc6791-addresses": true,
	"rfc6791v6-prefix": null,
	"rfc6791v4-prefix": null
},

(Actually, SIIT is a bit of a lost cause, because we can't provide a pool6 that will always work—users always need to define it according to their network. But this is as complete as it can be.)

Or you can just do what I do with the Debian package, which is keep the sample configuration as minimalist as possible. (Because I'm assuming that most users will not want to modify the global values.)

@tiagogaspar8
Copy link
Author

I see what you mean and maybe I'm not explaining myself correctly.

Let's assume that I leave the default configurations (witch I intend to) including manually-enabled as true.
When you select in OpenWRT the jool package, the building process automatically enables the packages to start at boot, witch isn't good and we cant change as it is default OpenWrt behavior.
So the jool package will be started at boot with the configuration files, and starts working with the configuration we add by default

The alternatives we have:

  1. Comment out all the configurations making jool do nothing (or apply the default config, not sure)
  2. Switch the manually-enabled config to false and that makes jool do nothing

See what I mean? I hope I'm explaining myself correctly.😅😅😅

@ydahhrk
Copy link
Member

ydahhrk commented Jan 8, 2020

Ah, I see.

  1. Switch the manually-enabled config to false and that makes jool do nothing

Well, perhaps one problem with this is that OpenWRT will think the service is enabled, even though Jool is technically disabled. It's going to look confusing, I think.

  1. Comment out all the configurations making jool do nothing (or apply the default config, not sure)

What I do in Debian is not provide default configuration files, and this naturally prevents the service from starting.

(This is partly because I have access to a thing called ConditionPathExists, which makes systemd check the file before attempting to start the service. But even if OpenWRT doesn't provide a ConditionPathExists, the missing files would still prevent the service from starting because jool file handle throws an error when it can't find the file.)

I actually do provide sample configuration files in Debian, but I do so in the dedicated example directory (/usr/share/doc/jool-tools/examples/). You can see that I ask users to copy the file they want in the documentation.

@tiagogaspar8
Copy link
Author

It's going to look confusing

I see what you mean, but people usually configure stuff, not using the default value. But I can add a "verification" that checks if the flag manually-enables is off and display a info reminder in the syslog.

the missing files would still prevent the service from starting because jool file handle throws an error when it can't find the file.)

Well, what kind of error? does it say "file /etc/jool/jool.conf.json not found"? or just says invalid file?

Also, in a recent test I ran into an issue:

Thu Jan  9 02:21:45 2020 kern.warn kernel: [837448.622609] jool: Unknown symbol target_ipv4 (err -2)
Thu Jan  9 02:21:45 2020 kern.warn kernel: [837448.627851] jool: Unknown symbol target_ipv6 (err -2)
Thu Jan  9 02:21:45 2020 kern.warn kernel: [837448.633142] jool: Unknown symbol jool_nat64_get (err -2)
Thu Jan  9 02:21:45 2020 kern.warn kernel: [837448.638631] jool: Unknown symbol jool_nat64_put (err -2)
Thu Jan  9 02:21:45 2020 kern.warn kernel: [837448.644168] jool: Unknown symbol target_checkentry (err -2)

Do you have any idea?

@ydahhrk
Copy link
Member

ydahhrk commented Jan 9, 2020

Well, what kind of error? does it say "file /etc/jool/jool.conf.json not found"? or just says invalid file?

# jool file handle /i/do/not/exist
Error: Could not open file "/i/do/not/exist": No such file or directory
# echo $?
2

Also, in a recent test I ran into an issue:

You installed jool.ko and (also presumably) jool_siit.ko, but not jool_common.ko.

See https://jool.mx/en/install.html#introduction

@ydahhrk
Copy link
Member

ydahhrk commented Jan 9, 2020

You installed jool.ko and (also presumably) jool_siit.ko, but not jool_common.ko.

jool_common is new; it first appeared in version 4.0.6 I believe.

@tiagogaspar8
Copy link
Author

Could not open file "/i/do/not/exist"

If that is the case We can do this: I'll leave a file with the default values named for example "jool_nat64.conf.json.defaults" that way when the program goes searching for the "jool_nat64.conf.json" file it won't find it, and won't run, leaving a entry in the syslog. I'll see if I can find a way for the start script to check for the file first and display a error message that I write. Do you agree?

jool_common is new; it first appeared in version 4.0.6 I believe.

AHA! That's why. the makefile doesn't foresee that third kernel module I believe. I'll get around to that.

@ydahhrk
Copy link
Member

ydahhrk commented Jan 9, 2020

If that is the case We can do this: I'll leave a file with the default values named for example "jool_nat64.conf.json.defaults" that way when the program goes searching for the "jool_nat64.conf.json" file it won't find it, and won't run, leaving a entry in the syslog. I'll see if I can find a way for the start script to check for the file first and display a error message that I write. Do you agree?

Yes, absolutely.

@tiagogaspar8
Copy link
Author

Hey!

I haven't forgotten about this issue, I just haven't been doing more cause I saw that @blocktronn has been working on the jool init and even uci configuration in his branch https://github.com/blocktrron/packages/tree/jool-init .
I'm currently waiting for developments on this matter before I put in more work.

@ydahhrk ydahhrk added Status: Stuck Development paused due to unavailable external input and removed Status: Not Started Progress is 0% labels Sep 24, 2020
@rnhmjoj
Copy link

rnhmjoj commented Feb 26, 2023

Couldn't this be simply a hook that rebuilds the BIB on changes to the WAN interface?
I don't think we gain anything useful by implementing this in jool: if the IP address changes connections are going to break anyway, so there's always going to be some downtime.
On openwrt I would imagine something like (untested)

$ cat /etc/jool/jool-nat64.conf.json.in
{
  "instance": "default",
  "framework": "netfilter",
  "global": { "pool6": "64:ff9b::/96" },
  "bib" : [
    { "protocol": "TCP", "ipv6 address": "2001:db8::1#22", "ipv4 address": "WAN_ADDR#22" },
    { "protocol": "TCP", "ipv6 address": "2001:db8::3#80", "ipv4 address": "WAN_ADDR#80" }
  ],
	"pool4": [
		{ "protocol": "TCP",  "prefix": "WAN_ADDR/32", "port range": "1-65635" },
    { "protocol": "UDP",  "prefix": "WAN_ADDR/32", "port range": "1-65635" },
		{ "protocol": "ICMP", "prefix": "WAN_ADDR/32", "port range": "1-65635" }
	]
}

$ cat /etc/hotplug.d/99-update-jool-bib
# if WAN is up
test "$INTERFACE" != "$WAN_INTERFACE" -o "$ACTION" != "ifup" && exit 0

# get WAN IPv4 address
. /lib/functions/network.sh
network_get_ipaddr WAN_ADDR "$WAN_INTERFACE"

# update the BIB
. /etc/init.d/jool
sed "s/WAN_ADDR/$WAN_ADDR/g" "$CONFIGFILE_NAT64.in" > "$CONFIGFILE_NAT64"

service jool restart

@rnhmjoj
Copy link

rnhmjoj commented Feb 26, 2023

Ok, I tested and it works perfectly fine. Here's a ready-made openwrt solution.
Just put the following into /etc/rc.local and update the BIB entries accordingly.

# install jool BIB update script
cat <<'EOF' > /etc/hotplug.d/iface/99-jool-bib
test "$INTERFACE" != wan4 -o "$ACTION" != "ifup" && exit 0
service jool restart
EOF

# configure stateful NAT64
cat <<'EOF' > /etc/jool/jool-nat64.conf.json.in
{
  "instance": "default",
  "framework": "netfilter",
  "global": { "pool6": "64:ff9b::/96" },
  "bib": [
    {
      "comment": "Forward WAN_ADDR:80 -> 2001:db8::1:80",
      "protocol": "TCP",
      "ipv4 address": "WAN_ADDR#80",
      "ipv6 address": "2001:db8::1#80"
    },
}
EOF

# patch init.d script to compute the WAN address
grep -q BIB /etc/init.d/jool || sed -i '/config_parser()/{
  i splice_config() {
  i \	# get WAN IPv4 address
  i \	. /lib/functions/network.sh
  i \	network_get_ipaddr WAN_ADDR wan4
  i
  i \	# update the BIB
  i \	sed "s/WAN_ADDR/$WAN_ADDR/g" "$CONFIGFILE_NAT64.in" > "$CONFIGFILE_NAT64"
  i }
  i
  } 
  /start()/{
  a \	splice_config
  }' /etc/init.d/jool

service jool restart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New feature Status: Stuck Development paused due to unavailable external input
Projects
None yet
Development

No branches or pull requests

3 participants