hyperboria / bugs

Peer-to-peer IPv6 networking, secure and near-zero-conf.
153 stars 17 forks source link

Non-cjdns routing instead of NAT66 #5

Open ghost opened 9 years ago

ghost commented 9 years ago

@tmartinx commented on 26 Mar 2014

Guys!

After reading the "nat-gateway.md" (https://github.com/cjdelisle/cjdns/blob/master/doc/nat-gateway.md) an idea just popup in my mind... Which is:

Instead of relying on this NAT66 thing, to share one cjdns router with my "private IPv6 subnet", I'm wondering here, why not publish my "IPv6 private subnet" to the entire cjdns network?

I mean, for example:

Behind my Hyperboria IPv6 address "fca8:b13e:41d3:3882:ab5a:d783:b920:633e" (cjdns instance), I have the following IPv6 private subnet: "fd9d:037d:2d95:6c4b::/64". So, as I said before, I would like to, somehow, publish my "fd9d:037d:2d95:6c4b::/64" private subnet to the entire Hyperboria, that way, if someone connected to it, tries to reach "fd9d:037d:2d95:6c4b::/64", the Hyperboria global network "will know" that this subnet is BEHIND the router "fca8:b13e:41d3:3882:ab5a:d783:b920:633e"!

And voialá! No need for NAT66!

What do you guys thinks about this idea?!

If it is doable, we can think later, in a mechanism that will not allow conflicts, subnet hijacking or routing table bloating (like external lookups or something else)...

I have lots more ideas, if this proposal works!! Like for example, deploy cjdns directly on a Neutron IPv6 router (from OpenStack project), this way, each tenant of my Cloud Computing environment, will be part of Hyperboria network without any effort!

BTW, sorry if this isn't the right place to talk about those kind of things...

Cheers! Thiago

@Downchuck commented on 28 Mar 2014

Thiago, I like the idea but you can't gloss over this one: "conflicts, subnet hijacking".

Seems to me that you're talking about something like DNS, with any non fc::0 resulting in something like a DNS lookup. I'd opt to re-use the trust semantics of cjdns -- in this case, I'd only trust mappings/routing as reported by nodes I'm directly connected to.

http://wiki.projectmeshnet.org/DNS#Current_state_of_DNS_on_Hyperboria

@tmartinx commented on 28 Mar 2014

Charles, I agree but, I also trust in a second decentralized database, called "Blockchain", I think that we can use the Namecoin, which is globally reachable, open source decentralized key/value registration and transfer system, as a place to host "cjdns routing info data by demand". Namecoin can also be used as a much more safer DNS. What do you think?! BTW, I'm glad you liked it! Tks! Cheers! Thiago

@t128 commented on 8 Apr 2014

But i dont want to expose my private network. The only reason for exposing a host to publicity is when it is a server. In this case i can just run cjdns directly on it. Also i can use a firewall to filter "bad" packets with nat.

ok, after rereading your text: it would be something like nat + exposure of your private net. I just dont see an advantage in this approach.

@tmartinx commented on 9 Apr 2014

Well, I think you don't understand my idea...

I agree, I'm thinking about running cjdns directly on a host that needs it, no problem with that, BTW...

But, NAT isn't a firewall, I never like this workaround called "NAT", and NAT66 is even worse. Need a firewall, use the filter table. :-P

No, I did not said "nat + exposure of your private net", nothing like that, my approach does NOT use any kind of NAT. It is pure routing, of course, to avoid NAT in first place. People should use the filter table to make its security polices.

Yes, I'm against NAT and I proposing this precisely to not make use of it.

From behind my cjdns router, I have a IPv6 network, that can be reachable from anywhere, people just need to know the route (again, no NAT). I build my firewall using the "filter" table, so, it will be protected anyway.

Cheers! Thiago

@Wolf480pl commented on 9 May 2014

I too don't like NAT. It was supposed to be gone with IPv6, wasn't it? Everyone was supposed to have a /48 or /56 prefix so that they can have several /64 subnets...

What would happen if cjdns only used first 64 bits of the public key hash for the first half of the IPv6 address, and the other half was be left to user, so that everyone had a /64 subnet? Would that cause many collisions?

Anyway, I guess it's too late to change it, it would break all the existing networks.

@nolith commented on 1 Aug 2014

Hi guys, I'm running a wireless community network node in Italy, which if part of the ninux.org network. We are using OLSR for internal routing and BGP over a tinc vpn with the other cities.

Yesterday I read about cjdns and hyperboria and I liked the idea. I was thinking of how to propose it to my community when I realized that this will require to run the cjdns on every machine :(

I'm with @tmartinx and @Wolf480pl, NAT was a necessary evil in IPv4 networks, but in IPv6 we need pure routing.

@cjdelisle commented on 1 Aug 2014

How do you imagine that working? One cjdns node has hundreds or thousands of IPv6 addresses and hands them out using DHCPv6 ?

@nolith commented on 1 Aug 2014

On 2014-08-01 09:27, Caleb James DeLisle wrote: How do you imagine that working? One cjdns node has hundreds or thousands of IPv6 addresses and hands them out using DHCPv6 ?

Radvd will be enough. Usually we have some wifi antennas on the rooftop which are connected to an openwrt router. We run olsrd on that and we bridge the wifi card to a tagged VLAN on the ethernet. So we have a taggeg interface for each antenna on the openwrt router. There we will be able to install the cjdn which will announce a /64 with radvd (which is already in place). In Rome they are using public IPv6 because the have found a free bpg peering, in Florence we are using ULA, in other cities are using tunnel broker. We have a network, scattered across Italy, of about 300 installations. But every node has a LAN which is announced via OLSR. End-To-End connection is a key value of our mesh network. --- Alessio "nolith" il sapere umano appartiene al mondo. GPG 440C5437

@cjdelisle commented on 1 Aug 2014

Ok, you want public addresses (not fc00/8) and you want to announce them with radvd and use cjdns to forward the traffic inside of your network. Take a look at this: https://github.com/cjdelisle/cjdns/tree/master/tunnel Each cjdns node will still have an fc00::/8 address for management purposes and without nat, you will not be able to expose your users to hyperboria (and packets from user-to-user will always go to the PoP) but this should resolve your use case of getting people on the internet.

@nolith commented on 1 Aug 2014

On 2014-08-01 10:24, Caleb James DeLisle wrote: [...] Each cjdns node will still have an fc00::/8 address for management purposes and without nat, you will not be able to expose your users to hyperboria (and packets from user-to-user will always go to the PoP) but this should resolve your use case of getting people on the internet.

No, I was just explaining you the whole scenario, but my idea is to be part of the hyperboria network, I think that in our network hyperboria and our mixed public/private addressing will coexists nicely. The whole idea behind cjdns is amazing and I would like to be part of it, but requiring to install it on every device will be a problem. Given the way we (ninux.org) but also others community network like freifunk, funkfeuer, guifi, wlan slowenija and awmn are used to deploy their networks, I fully support the idea of routing a /64 behind each cjdns router. So, I'll try as soon as possible to find some hyperboria peering over UDP to gain some experience about cjdns, but I cannot foresee a wide adoption whiteout a final prefix announcing to the home LAN.

@cjdelisle commented on 1 Aug 2014

Technically it's not possible to route a /64 in the hyperboria network because no matter how much you patch your cjdns nodes, the other nodes will look at your packets and if the double-sha512 of your public key doesn't match the ipv6, the packet is dropped so you would have to start your own network. The reason why we didn't elect to have some "routing room" in the ipv6 space during early design is because if nodes only relied on the first 64 bits matching, it would not take very long to collide someone's ipv6 and hijack their ip address.

@jedahan commented on 1 Aug 2014

Why not rely on the first 96 bits, or 112 bits? Is that still too easy to make collisions?

@cjdelisle commented on 1 Aug 2014

every bit removed makes it twice as easy to collide an ip and the people I talked to thought that 120 was a little bit scary in the long term. Maybe 116 would have been ok, you should have talked to us 2 years ago.

@nolith commented on 1 Aug 2014

@jedahan in IPv6 prefix smaller than /64 are prohibited (on RFC, not technically) only /128 is allowed.

@jedahan commented on 1 Aug 2014

So if I understand right, the reason we care about collisions is because people are self-assigning (algorithmically) ipv6 addresses. The benefit is no central service controlling address assignments, the drawback is we still have to NAT.

If we want no collision, self-assigned, cryptographically secure, no NAT ipv6 addressing & routing, we would need to:

a. ignore the /64 RFC to allow /12 prefixing (not a big deal imo) b. rewrite the rules for matching the first 116 bits instead of entire address (should not be painful?) c. have everyone who has peered have to re-peer (by far, the most painful part)

Being this is super alpha, I think some level of 'breakage' in the form of having to regenerate keys should be fine. As long as its announced ahead of time, and theres a well-documented way to migrate.

The medium and long-term benefits of killing NAT could really help adoption, and eventually the strength of the network, if i'm understanding things correctly.

If all of this was debated ad nauseum 2 years ago, and there are any logs, I would love to read them to get a deeper understanding and appreciation of the decisions made.

@Wolf480pl commented on 1 Aug 2014

To help avoid collisions you could also increase the difficulty of finding a good key. Right now there are 8 bits that need to be brute-forced (the fc/8 prefix), right? How bad would it be to add another 8?

@cjdelisle commented on 2 Aug 2014

256 times as hard for finding one. 65535 times as hard for finding all of them.

@t128 commented on 4 Aug 2014

This helps only against brute force attacks (128 bits to brute force vs. 128bit real range) but not against "random collisions" (112 bits vs. 128bit real range). Also it would make key-gen for every one harder.

@Arceliar commented on 8 Aug 2014

I don't think increasing the fixed prefix size will do much to the collision rate. Finding a collision means getting all 128 bits to match. Adding an extra 8 bits would make address generation 256x longer, and also make collisions 256x more common among valid addresses (since they now only need to match on the 112 free bits, and the rest are fixed).

Now, since the address is from a truncated hash, you could put requirements on bits we chop off (e.g. bits 129-136 must all be 0s), which would allow you to increase the time it takes to generate keys without increasing chance of collisions. But that would require people to generate new addresses and re-peer...

@jedahan commented on 8 Aug 2014

ohhhh that's a clever solution, Arceliar. +1

@lgierth commented on 8 Aug 2014

One issue I'm seeing with non-NAT routing to addresses outside of fc00::/8 is that we lose the end-to-end crypto guarantees, or am I missing something? What's the point of routing outside of fc00::/8 if the destination doesn't speak cjdns, and we lose all the benefits?

@vadipp commented on 9 Aug 2014

This thread mentions the need of re-peering. If I change my private key and IPv6, why will I have to re-peer? I might as well use the same connection info as before, right?

@kpcyrd commented on 9 Aug 2014

@vadipp re-peering is necessary if we change the criteria which address is considered valid and which one isn't. Old addresses will be considered invalid and therefore need to be replaced. This is a discussion about a possible future change, though.

@Arceliar +1. We can change the code for address generation without enforcing this criteria, yet, so we can slowly migrate without breaking the network.

@Arceliar commented on 17 Aug 2014

More thoughts on increasing address generation difficulty.

Another option would be to take another byte of the address (probably the byte immediately after 0xfc), and require that this byte equal the number of leading zero bits in the truncated part of the hash (beginning on bit 129).

That would make address generation 9 bits harder in the easiest case (8 bits in the address + exactly 0 leading zero bits), but allows people to extend the effective size of their address for the purpose of avoiding collisions. The truely paranoid could require an extra ~20 zero bits to increase the difficulty of a collision by a factor of ~1 million. Or just let it run for a week and then pick the best address found in that time.

Note that I'm not advocating that non-cjdns machines be given routable addresses, just trying to think of ways to mitigate the address collision problem if subnetting was ever allowed. I personally think it's a bad idea to do it any way outlined above. A better approach would be to have a cjdns router to assign its 1 and only address to another machine and just forward traffic. Then you could just run 1 instance of cjdns per client machine on your network. No need to change anything in the protocol. Not sure if it's already possible to set something like this up or not (I imagine so, but I don't know how... maybe some magic iptables command?).

@Arceliar commented on 2 Sep 2014

Followup on this. Had another thought.

It would also be possible to slightly change the address generation formula to simplify what I said in the previous post. Instead of the first 128 bits of a sha512, it could be first 128 bits with the first 16 overwritten by fcXX where, XX is the number of 0's following the address. (Or the first 112 bits prefixed with fcXX, or fc for the first bits and XX for the last, or whatever).

This would also have the side-effect of making valid address generation ~256x faster, if there's any incentive to do that.

IPv6s would change, but old keys would remain valid, so I think it would eliminate the need to re-peer. Paranoid users could brute force keys with lots of 0s following the address, to make it a bit more secure, if that's their thing.

@krattai commented on 4 Sep 2014

Just to chime in on NAT66, radvd, and external / internal traffic flow.

I'm not a fan of NAT, not much else to say about that. But, the alternative is being able to handle proper subnets, routing and possible BGP on the host system. This can be an issue for those who don't know how.. or shouldn't manage this, because they think they know how. ;)

Which then takes us to radvd vs DHCP, which is generally the simple solution in the NAT configuration above. radvd exposes the MAC address of the NIC. NOT a good thing from a security persecutive. So NATed router with an internal DHCPv6d on the inside is the more appropriate option, again because sometimes those that think they know how, shouldn't.

The word of this paragraph is "multi-home". IPv6 has integrated multihome, so a host can properly route to destination depending on which path (cjdns or non-cjdns) routes properly.

Not sure if this post provides any new insight or thought, but wanted to put it forward.

@cjdelisle commented on 23 Sep 2014

After some discussion we thought of a solution which might resolve your issue.

The problem is that right now you can't use any trick addressing without 100% of hyperboria dropping your packets, in effect this is like a feature request to change the rules of bitcoin, it only works after everyone updates.

A secondary problem is that whatever bits you use for your own purposes reduce the security against collisions (see also: Birthday Paradox)

I'm imagining you running some sort of ISP and wanting to provide people with both internet access and hyperboria access... In this case, you will likely be issuing a /64 of publicly routable IPv6 addresses to each node to which clients connect. Then clients will be issued individual IPv6 addresses from that /64.

I also have a public IPv6 address allocated to my laptop through cjdns/IPTunnel but if I were to communicate with you, the traffic would go out of my IPTunnel gateway, across the clearnet and back into your IPTunnel gateway (even if we were right next to eachother!)

What would you think of a way that we can "announce" our IPv6 (and IPv4) addresses to one another and bind them to the cjdns keys of the corresponding node?

Certainly your users would not be able to reach all of hyperboria but they would be able to reach anyone in hyperboria who participates in the publically-routable-IPv6 business.

The-Loeki commented 8 years ago

Hi, is there any progress on this? 'Cauz' it'd be awesomely super-usefull :)

I've been reading the discussion from 2014 from above and I've got a few ideas:

Just my 5c for now :)

steelman commented 8 years ago

NOTE: This isn't a technical remark but rather a "meetoo" one.

I learnt about cjdns quite recently and I like the idea. I've read some documentation and I'd like to share an observation. In my opinion the lack of inter-network routing is pretty much a showstopper. The FAQ document says:

Ultimately we hope to build a viable alternative to the regular internet, which we call clearnet. Our goal is to replace the existing hierarchical internet with a non-hierarchical model.

Sounds great but it is the inter-networking, i.e. connecting local networks, that made the "regular internet" successful. The model cjdns currently supports is like connecting mainframes in the early days of the Internet.

As much as IoT is a buzzword, it is a fact that more and more devices are connected to computer networks. We won't be able to run cjdns and hyperboria is going to be much less useful for users without those devices.

There needs to be a protocol that enables routing packets between nodes behind cjdns-enabled routers.

Wolf480pl commented 8 years ago

<nontechnical>

replace the existing hierarchical internet with a non-hierarchical model

and

internet = inter-networking

Now that I think of it, it looks like totally "nonhierarchical internet" couldn't possibly exist. If internet = inter-network, then we need at least one level of hierarchy in order to call ourselves an internet. And IMO it makes a lot of sense to have a 2-level hierarchy, like: "top: other people, bottom: my devices" </nontechnical>

As for the technical side of things:

The problem is that right now you can't use any trick addressing without 100% of hyperboria dropping your packets, in effect this is like a feature request to change the rules of bitcoin, it only works after everyone updates.

It would be cool to have a generic addressing trick, which can be introduced by having everyone update, and then doesn't require others to update for you to implement a specific addressing trick using it.

ghost commented 7 years ago

Hey guys!

Amazing to see more people talking about this! :-D

I have an idea to try to mitigate the address collision problem...

It is a solution similar to a tunneling technique called "6to4" (https://en.wikipedia.org/wiki/6to4), where you have an IPv6 address, that it is based on an IPv4 address (one address based on another address), "for example, the global IPv4 address 192.0.2.4 has the corresponding 6to4 prefix 2002:c000:0204::/48".

So, let's say that for each CJDNS IPv6 address, there will be a subnet "based on that address", for example, the global CJDNS IPv6 address "fcba:369d:c17:b9ed:c43d:925b:7840:f430" has the corresponding "6toH" prefix "fcba:369d:c17:b9ed::/48" (or whatever netmask we imagine now).

The downside is that we can't make up random IPv6 subnet/s and put it there, for Hyperboria to route it... Like the initial idea which might be awesome to have, I believe...

But the good side, I think, is that it can be easier to route this throughout the Hyperboria, again, similar to 6to4, but, lets call it "6toH" :-P , this way, Hyperboria can "know" in advance, which subnet is behind which router, by simple calculating the "6toH" prefix address (that is based on the current CJDNS IPv6 address).

At least, there is no conflict. Unless someone takes over your cjdroute.conf and duplicate your CJDNS instance route but, that's not different from today... Am I right?

These days, I'm installing CJDNS everywhere I can, following its principles (beans / end-points), which is is great but, I still think that it would be very nice to be able to route random IPv6 subnets via Hyperboria... Be it based on "6toH", or blockchain-based, like Namecoin or Ethereum App to host the data about who owns which IPv6 subnet behind which CJDNS IPv6.

BTW, I just found this bounty:

https://www.bountysource.com/issues/9310821-non-cjdns-routing-instead-of-nat66

Pretty awesome!! :-D

How much do you guys think that is needed to implement this feature?

Best! Thiago

steelman commented 7 years ago

This isn't a solution. The shorter prefix you choose (and 128 bit isn't too long at all) the easier it is find a colliding key and reroute traffic directed to someone else. fcba:369d:c17:b9ed::/48 network can be entered through both fcba:369d:c17:b9ed:1ac8:3d7e:b7e1:fdfe:64fa as well fcba:369d:c17:b9ed:c401:7b88:237a:9437:e32c. Which one is legitimate?

ghost commented 7 years ago

@steelman Oh, I understand that...

However, I used that prefix just as a bare useless example, only to bring this idea to the table.

Can we create a code/algorithm to generate this in a way that it becomes useful?

Or, you still think that this isn't a solution at all?

Wolf480pl commented 7 years ago

@tmartinx I'm pretty sure the idea has been mentioned before. The suggestion was to require the key fingerprint to have a few zero bits (at the end or beginning) in order to be allowed to claim a whole IP prefix. This way, you'd need to keep trying generating keys until you got one whose fingerprint has all those required bits (eg. last 8 bits) as zero. This would make it about 2^k more expensive to find such a key, and 2^k more expensive to find a collision (where k is the number of bits that are required to be zero).

The thing is, making any changes like this requires all nodes in the network to update, before any of them can start using the new feature. And if we can't do this in a backwards compatible manner, then anyone who updated will have their packets dropped by everyone who didn't update. And we have to get it right the first time.

steelman commented 7 years ago

Another solution from the top of my head is to change the hashing algorithm used to generate IPv6 address to provide more bits, use the top bits for the router address and the lower for network prefix. But this would definitely be backward-incompatible.

Wolf480pl commented 7 years ago

use the top bits for the router address and the lower for network prefix

What if there are other keys whose router address is within your key's network prefix? Or if there are two keys with same network prefix but different router address?

kpcyrd commented 7 years ago

Another solution from the top of my head is to change the hashing algorithm used to generate IPv6 address to provide more bits

We can't get more because ipv6 limits us to 128bits (8 of those are bruteforced to 0xfc). Changing the hashing algorithm won't change that :)

steelman commented 7 years ago

What if there are other keys whose router address is within your key's network prefix?

This one's easy. We need to reserve (backward incompatibly) one more bit (or more to be future-proof) in the address to designate the type of address: node (fc00:/9) or net (fc80::/9).

Or if there are two keys with same network prefix but different router address?

I told you it's off the top of my head (-; You are absolutely right. I need to think about it a little more.