Proxying Network Traffic Without a Hostname

Brandon Roldan
4 min readNov 20, 2022

Introduction

I was watching, liveoverflow’s tutorial series on game hacking. In part 9, he developed a proxy server to intercept the game traffic. https://www.youtube.com/watch?v=iApNzWZG-10 . But i noticed a problem with his approach. He knows that the game uses the hostname master.pwn3 and game.pwn3 to connect to the game.

With that, he can just easily, change the ip address of both of these hostnames to make it point to his macbook’s ip hosting the proxy server. But what will you do if there are no hostname, for example, assaultcube.

These servers uses hardcoded ip address and ports instead of hostnames. How can we intercept it? That was what we are going to find out

Doing the Research

Not really a research, i just asked this question in unknowncheats. https://www.unknowncheats.me/forum/general-programming-and-reversing/514224-relaying-game-proxy-server.html#post3524442

One answer does look really interesting.

So apparently, we can make an ip uses our loopback network interface, and in return, that ip will point to our localhost. This can be done with the command netsh int ip add address "Loopback" <IP> .

To test it out, i added the ip 66.175.235.209 to our loopback interface. I spawned a udp listener using netcat listening on localhost, and tried to send a udp packet to 66.175.235.209 .

import socket

UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

UDPClientSocket.sendto(b"to Localhost", ('66.175.235.209', 4444))

In theory, since i added 66.175.235.209 to my loopback interface, this packet, should be sent to my netcat listener in my localhost.

We can see, that it worked, the traffic, got redirected to our localhost. Now we can intercept all packets our local machine will make to any ip address. But, how can we forward these packets to the real ip address? While doing more research, i found out that, we can still connect to the real ip address, if we use our normal network interface. For that, i found this stackoverflow thread.

So i tried it out. Running ipconfig in command prompt, i got my ip address on my normal wifi interface.

import socket

UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPClientSocket.bind(('192.168.18.6', 0))

UDPClientSocket.sendto(b"to server", ('66.175.235.209', 4444))

If i run this, i shouldnt get the message to my netcat listener, since it will be forwarded to the real server. And it worked

Now that we know how to intercept traffic to an ip, and forward those traffic, we can now write our proxy

The proxy Server

import socket
from threading import Thread
import os


class Game2Proxy2Server(Thread):
def __init__(self, remote_ip, port) -> None:
super(Game2Proxy2Server, self).__init__()
self.server2proxy2game: Server2Proxy2Game = None
self.client_host = None
self.client_port = None
self.remote_host = remote_ip
self.port = port
self.sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
self.sock.bind((remote_ip, port))

def run(self):
while True:
data = self.sock.recvfrom(1024)
self.client_host, self.client_port = data[1]
print("[client] {}".format(str(data[0])))
self.server2proxy2game.sock.sendto(data[0], (self.remote_host, self.port))

class Server2Proxy2Game(Thread):
def __init__(self, local_ip, port):
super(Server2Proxy2Game, self).__init__()
self.game2proxy2server: Game2Proxy2Server = None
self.sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
self.sock.bind((local_ip, port))

def run(self):
while True:
if((not self.game2proxy2server.client_host) or (not self.game2proxy2server.client_port)):
continue
data = self.sock.recvfrom(1024)
print("[server] {}".format(str(data[0])))
self.game2proxy2server.sock.sendto(data[0], (self.game2proxy2server.client_host, self.game2proxy2server.client_port))

class Proxy(Thread):
def __init__(self, local_ip, remote_ip, port):
super(Proxy, self).__init__()
self.local_ip = local_ip #Your local ip in the network interface you are going to use
self.remote_ip = remote_ip #The ip of the game server you want to connect to
self.port = port # Port of the game the remote server is using

def run(self):
print("[proxy({}:{})] setting up".format(self.local_ip, self.port))
self.game2proxy2server = Game2Proxy2Server(self.remote_ip, self.port)
self.proxy2server2game = Server2Proxy2Game(self.local_ip, self.port)

self.game2proxy2server.server2proxy2game = self.proxy2server2game
self.proxy2server2game.game2proxy2server = self.game2proxy2server

self.game2proxy2server.start()
self.proxy2server2game.start()

proxy = Proxy('192.168.18.6', '18.159.92.242', 27763)
proxy.start()

while True:
try:
cmd = input('$ ')
if cmd[:4] == 'quit':
os._exit(0)
except Exception as e:
print(e)

This is based on the Proxy server that liveoverflow made. I uploaded it on github at https://github.com/tomorroisnew/Ip-based-Udp-Proxy. 18.159.92.242 is an assaultcube server running on port 27763 . So i added this ip to my loopback interface and ran the script.

We can see the game packets passing through our proxy server. From here, we can do anything we want to the game packets.

Conclusion

This approach would make it easier to intercept traffic to any ip without a hostname, or without knowing its hostname. My code is just a quick prototype, and it can still have alot of improvements. The only problem for now is that we can only redirect the ip to our localhost, and not to any ip we want. But in theory, it is still possible, but it would require setting up two proxy server. Thanks for reading.

Follow me On Twitter: https://twitter.com/tomorrowisnew__

--

--