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).


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...


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 :-)


  1. So will there be an extra Status tab showing which ports are open and mapped by NAT-PMP? That would be cool.
    Maybe email alerts?

    1. Status, yes, already in alpha release. email alerts, well, firewall rules allow that if you want.

  2. Given the scope be nice to even know what had tried but failed.

    1. Quite, you can enable on per subnet basis and see what mappings are created even if your fire-walling rules say they will not work.

  3. Rev, I know I am one of the many people that wrongly use NAT as a very crude firewall along with a basic set of firewall rules to explicitly allow or deny certain connections.
    As a result I am hesitant to start using IPv6 as I don't really know how to set it all up properly.
    Have you done/plan to do a primer or easy intro to setting up IPv6 the right way, or know of any good guides already? I've found online resources severely lacking or way too specific

    1. Most routers will automatically block incoming IPv6 sessions just as they do for an IPv4 NAT set-up. Usually IPv6 is allocated automatically on a LAN by the router. Generally, for an end user, it is simple and automatic - are you sure you don't have IPv6 already?

    2. Ok that's good to know.

      And yes and no, while I do have some level of IPv6, it's only the local addresses (starting fe80?) And I turned the rest off when I set it all up. Was a case of "I don't understand it yet so let's turn it off for now".

      I have my V6 allocation so would make sense to start using that, especially for public facing stuff


Comments are moderated purely to filter out obvious spam, but it means they may not show immediately. Also, Blogger seems to be a bit broken so I am having to manually check and hence comments may some times take days to show.