Factorio

Factorio

View Stats:
Prometheus Apr 11, 2016 @ 11:14am
Server behind NAT via UDP Hole Punching
Hey guys,

i wanted to share with you a neat little trick you can use if you cannot circumvent your local NAT (if you have no access to the router, etc.) and want to host a server behind that NAT without the use of VPN tools such as Hamachi, etc. This technique is called UDP Hole Punching and can come in quite handy in a number of applications (Wikipedia Link[en.wikipedia.org].

The setup has some severe limitations and will NOT WORK if you want your clients to be able to connect at any time.
So, basically, you and your clients will need to communicate with each other and they will have to connect to your server in a timespan of about 30 seconds after you start it (this time will vary depending on your NAT setup, but it will probably be at least 30s).

This works well if you and some friends just want to play a little bit together from time to time, and the upside is that you are connected directly over the internet and you will not need additional VPN tools.

Also, this post is aimed at people who have some experience with networking, and ideally programming stuff, like sockets, protocols, and such. I will make some scripts available for you to use, but if you have some crazy router that maps local and remote ports in a non-predictable way then you will need some experience and/or a server in the internet that tells you what external UDP port your local port is mapped to on your NAT router. Now, if you didn't understand any of that, i am sorry^^, you can try the scripts or ask for information, but i cannot promise you anything.

If you just want to try the bare minimum and hope for the best, read First Step - Easy Way and scroll to the bottom (TL;DR).

Now, lets start with the technical stuff:

First Step
Easy Way
Will probably work for most people.
Assumes your router maps your local port to the identical port number on his WAN interface.
Get your own and your clients' public (as seen from the internet) IP addresses from http://whatismyipaddress.com/ or some similar site. In the case of Factorio, the default UDP port is 34197. For example, the two addresses are:
  • Your server address: xxx.xxx.xxx.xxx:34197
  • Client's address: yyy.yyy.yyy.yyy:34197
where xxx.xxx.xxx.xxx and yyy.yyy.yyy.yyy are the addresses you get from whatismyipaddress.com.

Hard Way
Assuming your router maps your local port to a random port on his WAN interface
This is where it gets a bit more involved. For this to work you will need some server on the internet to tell you your external UDP port (the port on the router which is opened to the outside when you send a packet). I actually do not know any service that does this, hopefully someone in the comments can help here.
What you need to do when you have such a service at your disposal, is to bind a local UDP socket to the port on which you will start Factorio (server or client) and contact the service. The service then tells you on which port your local socket will be available from the internet.

At the end of this step, you need your own and your clients' public IP addresses and ports on which their Factorio instance is available.

Second Step
Bind a UDP socket to the same port on which you will start the Factorio server later (default 34197).
Now, (regularly) send each of your clients UDP packets on the port from which they will connect to your server (also default 34197), the content of those packets can be anything you want. The purpose of the packets is to tell your router to expect incoming UDP packets from your clients' addresses and Factorio ports so that it will not block them for some time.
For example, you send UDP packets from your local port 34197 to your clients address yyy.yyy.yyy.yyy:34197.

Third Step
Stop sending packets, close your socket to make the port available to Factorio and start the Factorio server on the same port from which you sent the packets.
Now, tell your clients to connect to the server within ~30 seconds.

Scipts

The main work here (the regular sending of UDP packets to clients) can quite easily be automated via some small scripts.
I wrote the scripts in python 3, just because its quite easy to understand and fast to write. So in order to run them, you will need the Python 3 interpreter (Download Link for x86-64 Windows version[www.python.org]).

And here are the scripts:
https://gist.github.com/anonymous/f9d3c1ce71968a1787dd006bea5048c4

The script most of you will be using will be
send_packets.py
, just replace/remove/add the client-address(es) in CLIENT_ADDRESSES as you need, run the script until your client is ready to connect, stop the script, start the server and tell your clients to connect.

The script
address_info_server.py
is just a small echo server that responds with the sender's IP address and port, i originally used it for getting my external port, but as it turns out, you won't need this in a lot of cases.
address_info_client.py
is just the client for the server.

TL;DR
  • Get your and your clients' public IP addresses (See First Step)
  • Install python 3
  • Run the
    send_packets.py
    script with replaced client address(es) (See Scripts).
  • Wait until clients are ready to connect
  • Stop the script
  • Start the Factorio server
  • Tell your clients to connect

Edit: Formatting
Last edited by Prometheus; Apr 11, 2016 @ 11:18am
Date Posted: Apr 11, 2016 @ 11:14am
Posts: 0