• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Proxy Tunnel Solution | With Client IP Passthrough

Michael Orsino

Premium User
Premium User
Support Team
Joined
Nov 15, 2007
Messages
854
Solutions
10
Reaction score
389
Location
Santiago, Chile (Australian)
Proxy Tunnel Solution | With Client IP Passthrough
Written by Michael Orsino for dura-online who have kindly chosen to contribute this back to the community
Difficulty level: Medium - this guide assumes some linux & firewall knowledge
Reading time: 4 minutes

What is this?
A solution for setting up a forward proxy to tunnel connections, respecting the original IP address of the client.
Why do I need this?
Strategically located forward proxy tunnels may improve the latency and reliability of connections to your services. (this is not the place to debate that - tire yourself out on reddit instead please). The solutions provided in this guide are also applicable for security and load balancing configurations.
Typically in these configurations the IP address of the client is lost and the service can only see the IP address of the proxy server itself. This is problematic for a few reasons such as logging; moderation; server list reporting; mc checking.
With this solution the IP address of the client is respected and all features of the service will operate as usual.
How does it work?
It is indistinguishable from magic.
If you're interested on a technical networking level, check out this cloudflare blog post.
Are there alternatives?
Yes, there are alternative solutions to this problem and also different ways of configuring this solution. I believe this to be both the simplest in terms of deployment and best in terms of maximum connections and Mbps throughput.
The cloudflare article linked above talks about some of the alternatives.
One notable alternate solution is to pay Kondrah USD$1500 for his system, but I cannot speak to how well it works.

1.) Prerequisites
  • Game server running on Linux (This guide will assume Ubuntu 20.04)
  • A secondary Linux server to be the proxy (e.g. $10/month DDoS protected VPS)
  • Necessary ports opened in the firewalls of both servers. You can use whatever you like, but for this guide we will use the following:
    • Game server: 7172 TCP (TFS game), 7173 TCP (proxy listener)
    • Proxy server: 7172 TCP (proxy listener)
2.) Configure the forward proxy server
For your forward proxy server I'll provide instructions for two options: #1 HAProxy; #2 NGINX.
Which should you use? If you're already using NGINX for something else, use it for this too. If not, use HAProxy.

Preliminary
$ sudo apt update

$ sudo apt-get update
$ sudo apt upgrade

Option #1: HAProxy
$ sudo apt install haproxy
$ sudo vim /etc/haproxy/haproxy.cfg
  • Press shift+g to jump to the last line of the file and then press $ to jump to the end of the line. Alternatively use the arrow on your keyboard until you reach the end of the last line
  • Press the letter i on your keyboard to switch to insert mode
  • Type in the following, replacing 123.456.78.9 with the IP of your actual game server
Code:
listen game
  bind 0.0.0.0:7172
  mode tcp
  server game 123.456.78.9:7173 send-proxy
  • Pres the Esc key to turn off insert mode
  • Press the colon key (shift+; on a U.S. keyboard layout) to enable command mode
  • Type in wq and press enter
$ /etc/init.d/haproxy restart
  • If you need to add additional listeners, simply provide a new config for it underneath with a unique listen name e.g. listen login instead of listen game
Option #2: NGINX
$ sudo apt install nginx
$ sudo vim /etc/nginx/nginx.conf
  • Press shift+g to jump to the last line of the file and then press $ to jump to the end of the line. Alternatively use the arrow on your keyboard until you reach the end of the last line
  • Press the letter i on your keyboard to switch to insert mode
  • Type in the following, replacing 123.456.78.9 with the IP of your actual game server
Code:
stream {
  server {
    listen 7172;
    proxy_pass 123.456.78.9:7173;
    proxy_protocol on;
  }
}
  • Pres the Esc key to turn off insert mode
  • Press the colon key (shift+; on a U.S. keyboard layout) to enable command mode
  • Type in wq and press enter
$ sudo /etc/init.d/nginx restart
  • If you need to add additional listeners, simply provide a new config for it underneath inside a new server table
3.) Configure the Game Server
$ sudo apt install golang
$ go get github.com/path-network/go-mmproxy
$ sudo ip rule add from 127.0.0.1/8 iif lo table 123
$ sudo ip route add local 0.0.0.0/0 dev lo table 123
$ sudo ip -6 rule add from ::1/128 iif lo table 123
$ sudo ip -6 route add local ::/0 dev lo table 123
$ screen -aS mmproxy
$ cd go/bin/
$ sudo ./go-mmproxy -l 0.0.0.0:7173 -4 127.0.0.1:7172 -6 [::1]:7172 -p tcp -v 2
- Press ctrl+a+d to detach from this screen session

The go-mmproxy invocation command looks a little intimidating at first, but it is actually pretty straight forward. You can read more about the individual switches here.

Thats all folks! I hope this guide proves to be useful for some people either in an otserv application or even for their real life jobs as this guide has application far beyond otserv hosting!
If you find this guide useful and especially if it saves you USD$1500 please consider buying me a coffee!

Credits:
Path Network for creating the go-mmproxy utility this guide relies on;
Michael for writing this guide;
Dura Online for releasing it to the community.
 
Last edited:
Not having a good way to pass the client IP through to the game server (pretty important in the case of my server Ascarus) is what prevented me from offering proxy solutions to our players in 2016 already, never looked into it again much since then. Thanks to this useful info about mmproxy I might get around to adding proxies for our players after all. The code in our login server has been sitting there unused for years

MybdM6n.png
gEVzbCG.png
 
05/02/2024 - Adding a quick note to this - since originally posting, the routing between Brazil and Europe has gotten significantly better and more providers are now utilising EllaLink. I've personally experienced ~140ms between Sao Paulo & Warsaw on a private network over EllaLink (expensive) and 155ms between Fortaleza and Frankfurt on the public internet over EllaLink (reasonable).

Case Study - AcidsOT.com
AcidsOT is hosted by @Znote with OVH in France. Typically players from within Europe have a great connection however players in Brazil particularly suffer from high latency and unreliable connections.

Question
How can we improve the connection to AcidsOT for players in Brazil?
Considerations
1.) Why are the connections from Brazil particularly bad?
2.) How can we optimize those connections?
3.) What providers should be considered?

Consideration #1 - Why are the connections from Brazil particularly bad?
Brazil is really really far away from France, particularly in terms of network routing. Distance is typically the biggest factor in latency.
Brazil is a really really staggeringly big country covering approximately 8.5 million square kilometers with a coastline approximately 8500kms long. Let me put that in perspective for you. All of Europe including Russia is only approximately 18% larger, and the distance between New York & London is only about 6000kms.
It's the coastline of Brazil that we are particularly interested in though, specifically the landing points of submarine telecommunications cables. Without going into too much detail - depending on where you are in Brazil and who your ISP is - your internet connection will leave Brazil via one of the submarine cables and follow a particular route till it reaches its destination in France. Not all routes are equal. If you run trace routes from various locations in Brazil you can see this happen and you can see the impact it can have on latency. If you want to go a step further you can use a tool like mtr to also see the impact on packetloss and jitter.

Consideration #2 - How can we optimize those connections?
From my own extensive testing working directly with a large Brazilian player base, tunnelling their connections from anywhere in Brazil through Sao Paulo results in the lowest latency to US-EAST, which in turn has the lowest latency to Europe. A rough estimate of the best latency we can expect would be 310ms. To achieve this we would locate a forward proxy in Sao Paulo, and possibly another forward proxy in US-EAST.
An alternate route that may prove better would be Fortaleza to Spain - unfortunately I do not have data on this - I'd encourage people to investigate this route themselves.

Consideration #3 - What providers should be considered?
Generally speaking large hosting providers like OVH will have optimized routes between their own datacenters, so ideally we want our proxy server(s) hosted with OVH too (Remembering that AcidsOT is currently hosted with OVH in France)
Unfortunately OVH does not have a datacenter in Sao Paulo (or anywhere in Brazil), so we must look for an alternative.
In searching for an alternative I'd consider two main things: a.) Does OVH peer directly with this provider and; b.) Does this provider offer any level of protection?
Rather than fill this case study with investigatory data, I'll just tell you that I use Amazon Web Services for this purpose in Sao Paulo.
OVH peer directly with Amazon at all of their major points of presence which means they're going to have a pretty great connection between them.
Unfortunately AWS does not offer much in the way of DDoS mitigation unless you're paying them huge amounts of money, but it still wins as far as I am concerned for a proxy server provider in Sao Paulo because the only companies that do offer more DDoS mitigation in Brazil will also null route you if you ever get close to their mitigation capacity anyway (watch out dolera-global!)

Solution
With the considerations above in mind I would look to provide the following:
1.) Forward proxy in Sao Paulo with AWS [br1.acidsot.com]
t3.nano instance (port speed up to 5gbps) [Note: EC2 instance network performance can be sub-par unless you're paying for a bigger port - we don't need 5gbps, but we do need high performance, and with AWS they come together]
2.) Forward proxy in Beauharnois Canada with OVH (or Vint Hill, Virginia with OVH if you have a U.S. billing address). [na1.acidsot.com]
"value" VPS (port speed 250mbps) [Note: You only need about 1mbps/100 concurrent players.]

Configure the Sao Paulo "br1.acidsot.com" forward proxy to do two things:
1.) Listen on port 7172 - forward connections to na1.acidsot.com:7172
2.) Listen on port 7173 - forward connections directly to acidsot.com:7173

Configure the OVH "na1.acidsot.com" forward proxy to do one thing:
- Listen on port 7172 - forward connections directly to acidsot.com:7173

Configure mmproxy on the game server "acidsot.com" to do one thing:
- Listen on port 7173 with mmproxy magic - passing connections through on port 7172

With this configuration your players in Brazil can be given multiple options and decide for themselves which gives them the best connection:
a.) Connect directly with the game server (if you allow this);
b.) Connect via your fully defined route br1.acidsot.com:7172 -> na1.acidsot.com:7172 -> acidsot.com:7173;
c.) Connect via br1.acidsot.com:7173 -> acidsot.com:7173
 
Last edited:
Proxy Tunnel Solution | With Client IP Passthrough
Written by Michael#4463 for dura-online who have kindly chosen to contribute this back to the community
Difficulty level: Medium - this guide assumes some linux & firewall knowledge
Reading time: 4 minutes

What is this?
A solution for setting up a forward proxy to tunnel connections, respecting the original IP address of the client.
Why do I need this?
Strategically located forward proxy tunnels may improve the latency and reliability of connections to your services. (this is not the place to debate that - tire yourself out on reddit instead please). The solutions provided in this guide are also applicable for security and load balancing configurations.
Typically in these configurations the IP address of the client is lost and the service can only see the IP address of the proxy server itself. This is problematic for a few reasons such as logging; moderation; server list reporting; mc checking.
With this solution the IP address of the client is respected and all features of the service will operate as usual.
How does it work?
It is indistinguishable from magic.
If you're interested on a technical networking level, check out this cloudflare blog post.
Are there alternatives?
Yes, there are alternative solutions to this problem and also different ways of configuring this solution. I believe this to be both the simplest in terms of deployment and best in terms of maximum connections and Mbps throughput.
The cloudflare article linked above talks about some of the alternatives.
One notable alternate solution is to pay Kondrah USD$1500 for his system, but I cannot speak to how well it works.

1.) Prerequisites
  • Game server running on Linux (This guide will assume Ubuntu 20.04)
  • A secondary Linux server to be the proxy (e.g. $10/month DDoS protected VPS)
  • Necessary ports opened in the firewalls of both servers. You can use whatever you like, but for this guide we will use the following:
    • Game server: 7172 TCP (TFS game), 7173 TCP (proxy listener)
    • Proxy server: 7172 TCP (proxy listener)
2.) Configure the forward proxy server
For your forward proxy server I'll provide instructions for two options: #1 HAProxy; #2 NGINX.
Which should you use? If you're already using NGINX for something else, use it for this too. If not, use HAProxy.

Preliminary
$ sudo apt update

$ sudo apt-get update
$ sudo apt upgrade

Option #1: HAProxy
$ sudo apt install haproxy
$ sudo vim /etc/haproxy/haproxy.cfg
  • Press shift+g to jump to the last line of the file and then press $ to jump to the end of the line. Alternatively use the arrow on your keyboard until you reach the end of the last line
  • Press the letter i on your keyboard to switch to insert mode
  • Type in the following, replacing 123.456.78.9 with the IP of your actual game server
Code:
listen game
  bind 0.0.0.0:7172
  mode tcp
  server game 123.456.78.9:7173 send-proxy
  • Pres the Esc key to turn off insert mode
  • Press the colon key (shift+; on a U.S. keyboard layout) to enable command mode
  • Type in wq and press enter
$ /etc/init.d/haproxy restart
  • If you need to add additional listeners, simply provide a new config for it underneath with a unique listen name e.g. listen login instead of listen game
Option #2: NGINX
$ sudo apt install nginx
$ sudo vim /etc/nginx/nginx.conf
  • Press shift+g to jump to the last line of the file and then press $ to jump to the end of the line. Alternatively use the arrow on your keyboard until you reach the end of the last line
  • Press the letter i on your keyboard to switch to insert mode
  • Type in the following, replacing 123.456.78.9 with the IP of your actual game server
Code:
stream {
  server {
    listen 7172;
    proxy_pass 123.456.78.9:7173;
    proxy_protocol on;
  }
}
  • Pres the Esc key to turn off insert mode
  • Press the colon key (shift+; on a U.S. keyboard layout) to enable command mode
  • Type in wq and press enter
$ sudo /etc/init.d/nginx restart
  • If you need to add additional listeners, simply provide a new config for it underneath inside a new server table
3.) Configure the Game Server
$ sudo apt install golang
$ go get github.com/path-network/go-mmproxy
$ sudo ip rule add from 127.0.0.1/8 iif lo table 123
$ sudo ip route add local 0.0.0.0/0 dev lo table 123
$ sudo ip -6 rule add from ::1/128 iif lo table 123
$ sudo ip -6 route add local ::/0 dev lo table 123
$ screen -aS mmproxy
$ cd go/bin/
$ sudo ./go-mmproxy -l 0.0.0.0:7173 -4 127.0.0.1:7172 -6 [::1]:7172 -p tcp -v 2
- Press ctrl+a+d to detach from this screen session

The go-mmproxy invocation command looks a little intimidating at first, but it is actually pretty straight forward. You can read more about the individual switches here.

Thats all folks! I hope this guide proves to be useful for some people either in an otserv application or even for their real life jobs as this guide has application far beyond otserv hosting!
If you find this guide useful and especially if it saves you USD$1500 please consider buying me a coffee!

Credits:
Path Network for creating the go-mmproxy utility this guide relies on;
Michael for writing this guide;
Dura Online for releasing it to the community.
I'm following this guide but when i try to login i get this
[warning] [ServicePort::eek:pen] - Error: bind: Address already in use [system:98]
 
when connecting the client of the following error

connect: connection timed out","dropConnection":true

Lua:
{"level":"debug","ts":1682918305.49094,"caller":"go-mmproxy/tcp.go:31","msg":"new connection","listenerNum":0,"protocol":"tcp","listenAdr":"0.0.0.0:7173","remoteAddr":"18.231.xxx.xxx:49470","localAddr":"10.182.0.4:7173"}
{"level":"debug","ts":1682918305.4910467,"caller":"go-mmproxy/tcp.go:68","msg":"successfully parsed PROXY header","listenerNum":0,"protocol":"tcp","listenAdr":"0.0.0.0:7173","remoteAddr":"18.231.xxx.xxx:49470","localAddr":"10.182.0.4:7173","clientAddr":"179.xxx.xxx.152:56523","targetAddr":"34.125.xxx.xxx:7172"}


help me?
 
when connecting the client of the following error

connect: connection timed out","dropConnection":true

Lua:
{"level":"debug","ts":1682918305.49094,"caller":"go-mmproxy/tcp.go:31","msg":"new connection","listenerNum":0,"protocol":"tcp","listenAdr":"0.0.0.0:7173","remoteAddr":"18.231.xxx.xxx:49470","localAddr":"10.182.0.4:7173"}
{"level":"debug","ts":1682918305.4910467,"caller":"go-mmproxy/tcp.go:68","msg":"successfully parsed PROXY header","listenerNum":0,"protocol":"tcp","listenAdr":"0.0.0.0:7173","remoteAddr":"18.231.xxx.xxx:49470","localAddr":"10.182.0.4:7173","clientAddr":"179.xxx.xxx.152:56523","targetAddr":"34.125.xxx.xxx:7172"}


help me?
These are not errors, what you can see here are the connection state change log.
If you don't want to see this, you can change the -v flag value to 0.

Unfortunately I cannot see what might be actually wrong with your configuration without a lot more information (too much for in this thread) or access to the machine. You can contact me on Discord if you need further support.
 
Last edited:
I can connect the client to mmproxy as soon as I reinstall a machine using TFS. However, moments later it gives "failed to establish upstream connection" errors and no longer logs in to the client.

In Canary, unlike TFS, it doesn't even log in. Perhaps the game code has some blocking.
 
Hi @Michael Orsino, first thanks for sharing this knowledge.
I did the proxy implementation on my server but I'm having some ping problems that I don't know how to trace the problem.
My server is hosted in the European Union (Germany) and I have about 220ms from Brazil.
Then I acquired a proxy server located in Belo Horizonte (35ms ping from my machine), but inside the client I see 270/275ms on Brazil proxy:
1686662542312.png
Ignore this Dallas, it's European Union.

Any idea how I can investigate/tshoot this?

Thanks in advance!
 
Back
Top