Showing posts with label NAT. Show all posts
Showing posts with label NAT. Show all posts

2020-02-04

VPN on a ship

There are many reasons for a VPN on a ship, and I was quite impressed that my other hack for UDP over fake TCP worked at all.

It did work, but was slightly strange. The experience was that normally VPN (via UDP or TCP) worked, but had 700ms latency round trip.

However, some of the time, the ship would have packet loss on the back haul, and then things changed. The UDP VPN would lose enough packets that normal TCP really struggled. Indeed, some times the VPN itself struggled to establish or stay up. It was actually for this reason that we even tried the TCP based solution.

However, in such cases, the TCP based VPN is special. It is very reliable, but has silly latency (up to many seconds).

The reason is what the satellite link it doing behind the scenes with TCP. It is doing an accelerator, which (I assume) is some level of local ACK combined with some internal re-transmission for dropped packets. But this means our VPN over TCP has the problems of doing TCP properly rather than faked, in that dropped packets result in high latency for every following packet.

Given the "cleverness" going on, it is amazing our faked TCP was good enough at all!

However, we like to have proper IP addresses here. There are a lot of reasons for that, but one of them is simple, it puts us, and our apple TV, geo-located at home. This was rather important for watching the episodes of Picard as they came out, even when in the middle of the Pacific.

So the challenge was proper UK IP addresses but still using the ship's TCP acceleration.

The solution was to de-NAT the traffic. The local brick here would NAT and send via ship's internet, which NATs again, but we change the destination IP to go to a brick in the UK. That then de-NATs, mapping back to original source and destination IP addresses and ports, or NAT the source. This works a treat, but you may have spotted the challenge here... How does the far end know where you wanted to send the packets in the first place?

The answer was to tack them on to the TCP SYN and look a them at the remote end!

My first thought was push them in to TCP options, but that is a challenge as there are only 40 bytes, and MSS takes 4 of those, leaving not enough bytes for two IPv6 addresses and ports. We could for IPv4, or we could just send target IP/port and NAT in UK. So we tried that.

The buggers NOP out any TCP option they do not understand, arrrg!

Alternative was put actual data in the initial SYN. To our surprise that worked, and as a SYN does not normally carry data, it works well (it is one of those theoretical TCP things I have never seen used). But it survives, and does not have the small size limit. We do have to move the SEQ back to allow for it, and strip out at the far end before sending on, but end result is public IPv4 and public IPv6 here, working. There is even space to add some authentication. (Note, this is not encrypted as assumes we will encrypt over it with TLS/https, ssh, etc).

Sadly sessions do not persist over glitches, and no incoming sessions, but I could watch Picard, so mission accomplished.

P.S. We have a choice of how to connect now, VPN over UDP, TCP (faked), relayed TCP, or just NAT on to ship's network raw (no good for Apple TV). Today we found UDP the best - the ship's TCP was unbearably slow (relaying, or not), but UDP was way better. To be honest this is much more what we are used to - everyone on the ship saying internet is crap and we're like "high latency, but not bad really" because the UDP based VPN works so well. The main thing is we can switch between different approaches as needed on a trip like this.

2017-11-06

NAT is evil, and really, not a good firewall, honest

I have been busy today with some new code on the FireBrick for two protocols (RFC6886 and RFC6887) which provide ways to get through NAT and firewalls.

What's the problem?

The original design of the Internet had all device's interfaces having a globally unique IP address that could send and receive packets on the Internet as a whole. This is great but for two small flaws: (a) There were not enough IPv4 addresses for that, and (b) Code is stupid, and hackers are not, and so we need firewalls.

So the classic scenario is a network (home or office) behind a router which does NAT and has one external IPv4 address (which may or may not occasionally change).

Please! NAT is not a firewall!

And yes, even FireBricks allow this set up, doing basic NAT on all outgoing sessions as well as allowing a wide variety of mapping configurations - if you can be bothered to set them up.

The classic scenario has a pretty simple router and simpler end users where they do not want the hassle of configuring mappings, and so this causes issues with anything on your network which would like an "incoming connection" to get to it.

NAT is evil!

NAT is a problem for so many reasons. It stifles development of protocols. It just makes life difficult. The usually answer is, of course, use IPv6.

The problem is that people still need the fire-walls. So even on IPv6 you have to ask how the incoming connections get past the fire-wall?

The solution!

Have a protocol so devices on your LAN can tell your router to map or allow some incoming connections. Simples!

This started with uPnP (Universal Plug 'n' Play). Yes, 'n' should be 'and' and so it should be uPaP, but what the hell? My understanding of uPnP is it is a can of worms, so we have steered clear of that, sorry.

However, there is more. There are newer protocols. NAT-PMP (Network Address Translation - Port Mapping Protocol), and PCP (Port Control Protocol, not angel dust, honest).

NAT-PMP

The NAT-PMP (RFC6886) protocol is beutifily simple. Really, it is very very simple - it is a UDP packet sent from a device on your LAN to your router which can ask one of two things: (a) What is my external IP address?, and (b) Please map something to this port on my address. The latter can be TCP or UDP, and allows a suggestion of the external port to assign if possible as well as setting a timeout. The mapping has a lifetime and can be renewed. The reply says which external port was assigned.

That is it. IPv4 only, but incredibly simple for server (router) and client. Noddy in the extreme.

I love it for its simplicity - it has taken literally a few hours to implement on FireBrick. The hard part is making it so fire-walling rules can decide which mappings are allowed.

But you do have to think of security here - let's be clear: ANY DEVICE on your LAN can send a single UDP packet to allow incoming connections to ANY DEVICE on your LAN!

Yes, in theory, "third party" requests are not allowed, but the router has no way to know if a source IP (and even MAC) is spoofed on a LAN. A virus or rouge app able to send UDP packets can just open up your LAN just like that! Really, NAT is not a fire-wall!

This is why we decided to make the FireBrick allow configurable fire-wall rules to decide what mappings are allowed...

PCP

What about IPv6? Well the answer is RFC6887 PCP (Port Control Protocol) which provides some cool extra features. The main one is handling IPv6, but in theory it could talk over CGNAT as well, and allows it to do a few more things.

Firstly the "what is my external IP" has gone, in favour of "what external IP was allocated this time for this mapping". Very sensible when considering things like CGNAT which may have many external IP addresses.

It then has the two main types of request - one is to create an new incoming mapping to a port (just like NAT-PMP) but the other is to create a new explicit outgoing mapping and get confirmation that it worked, and what external IP and port have been used. The latter is easy (just send a packet) but harder to control what ports or see what ports and IP have used, so PCP solves that nicely.

It is also designed to allow for the internal and external IP and ports to match (which could just as easily apply for NAT-PMP in theory) to allow simple firewall holes to be made where there is no NAT (as is normal for IPv6, obviously). NAT is evil, after all.

It is slightly more complex, so I may code support tomorrow. Again, fire-wall rules to define what is allowed and not.

PCP allows for explicit third party mappings to be made, and suggests a gateway should not do them unless expressly told to allow them. But they are still just a UDP packet, so again ANY DEVICE on your LAN can send a single UDP packet to allow incoming connections to ANY DEVICE on your LAN!

Which is a risk, obviously.

It's all in the app!

One thing that took me a while to realise is that it is not down to the operating system of the machine or console - e.g. does Windows support NAT-PMP and/or PCP, etc. It is down to the application.

An application can send the message to open a port, simple as that. So actually it is down to which applications support these protocols.

I suspect for the likes of game consoles, where this can be important for hosting games, this may be console dependant rather than per game - I hope so. We will see :-)

QR abuse...

I'm known for QR code stuff, and my library, but I have done some abuse of them for fun - I did round pixels  rather than rectangular, f...