Simple 1 on 1 chats are too boring since we’ve tried a multiperson chat before, so let’s try a 1:1 chat, but through a proxy, specifically a reverse proxy! This adds an additional layer of anonimity to our servers since we hide our location which adds security!
What’s a reverse proxy?
Source: linuxbabe
The idea of a reverse proxy is for use with a server, it hides our server’s IP (as long as the proxy isn’t compromised) but still allows clients to connect to our server and have a 2-way data transfer because the proxy itself is also a server, a proxy server.
Here’s what a normal client-server connection looks like.
The problem with this, is that if a malicious user connects, the attacker will be able to attack our server immediately, so to counter that, here’s what we’ll be making.
As you can see, our client isn’t actually connecting to the real server (on port 1234
), but it’s connecting to the proxy server (on port 4321
), which is connected to the real server. We can also add additional layers of security on our proxy server such as filters, ip blocking, timeouts, etc. or even more advanced stuff like load balancing.
Note that this is an example scenario, a real scenario would be where the real server’s IP is never disclosed and only the proxy server knows where it is. Also let’s pretend msg_with_payload
is an attempted RCE attack payload.
Here’s server.py, downloadable here
#!/usr/bin/python
# https://www.binarytides.com/code-telnet-client-sockets-python/
import sys
import socket
import select
import string
if len(sys.argv) != 3:
print "Usage: server.py [server_ip] [server_port]"
print " Sets up a basic 1 to 1 chat server"
print " For localhost connections, set server_ip to 0.0.0.0"
exit()
addr = sys.argv[1]
port = int(sys.argv[2])
s = socket.socket()
s.bind((addr,port))
s.listen(1)
print "[+] server live at %s:%d" % (addr, port)
# waits for connection (holds/blocks script)
client_socket,addr = s.accept()
print "[+] %s connected, binded to port %d" % (addr[0], addr[1])
while 1:
sockets = [sys.stdin, client_socket] # diantara 2 stream ini
read, write, error = select.select(sockets, [], []) # yg mana dulu yg "diinput"
for sock in read:
if sock == client_socket: # kalo dari client ada ngomong
try:
msg = client_socket.recv(2048) # print apa yg client bilang
if len(msg):
print "client> "+msg
except Exception as e:
print e
print "[-] %s disconnected" % addr[0]
exit()
else: # kalo kita yg ngomong
msg = sys.stdin.readline() # kasi tau kita ngomong apa
msg = string.rstrip(msg)
try:
client_socket.send(msg)
except Exception as e:
print e
print "[-] %s disconnected" % addr[0]
exit()
It’s simpler because we only have to connect to 1 client, so no need for holding an array of active clients, broadcasting, etc.
Here’s client.py, downloadable here
#!/usr/bin/python
# https://www.binarytides.com/code-telnet-client-sockets-python/
import sys
import socket
import select
import string
if len(sys.argv) != 3:
print "Usage: client.py [server_ip] [server_port]"
print " Connects to a basic 1 to 1 chat server"
print " For localhost connections, set server_ip to 0.0.0.0"
exit()
dest = sys.argv[1]
port = int(sys.argv[2])
srv = socket.socket()
try:
srv.connect((dest,port))
except Exception as e:
print "[-] Server down"
exit()
while 1:
sockets = [sys.stdin, srv]
read, write, error = select.select(sockets, [], [])
for sock in read:
if sock == srv: # kalo dari server ada ngomong
try:
msg = srv.recv(2048)
if len(msg):
print "server> "+msg
except:
print "[-] server down"
exit()
else: # kalo kita yg ngomong
msg = sys.stdin.readline()
msg = string.rstrip(msg)
try:
srv.send(msg)
except:
print "[-] server down"
exit()
We can see that client.py is really similar to server.py outside of the client doing the connecting and the server doing the listening.
Here’s proxy.py, downloadable here
#!/usr/bin/python
# https://www.binarytides.com/code-telnet-client-sockets-python/
import sys
import socket
import select
import string
if len(sys.argv) != 5:
print "Usage: proxy.py [proxy_ip] [proxy_port] [server_ip] [server_port]"
print " Sets up a proxy server at proxy_ip that forwards connections to server_ip"
print " Only 1 connection at a time"
print " For localhost connections, set server_ip to 0.0.0.0"
exit()
myip = sys.argv[1]
myport = int(sys.argv[2])
srvip = sys.argv[3]
srvport = int(sys.argv[4])
srv_socket = socket.socket()
try:
srv_socket.connect((srvip, srvport))
except:
print "[-] Server down"
exit()
print "[+] connected to tcp server at %s:%d" % (srvip, srvport)
# nunggu koneksi dri client
mysocket = socket.socket()
mysocket.bind((myip, myport))
mysocket.listen(1)
client_socket,addr = mysocket.accept()
print "[+] client %s connected, now connecting to chat server %s" % (addr[0], srvip)
def filter_msg(msg):
if msg == "msg_with_payload":
print("[!] client just attempted an attack!")
msg = "filtered_msg"
return msg
# skrg kita punya 2 socket idup
# client_socket ama srv_socket
while 1:
sockets = [client_socket, srv_socket]
read, write, error = select.select(sockets, [], [])
for sock in read:
if sock == client_socket: # client mau send ke srv
try:
msg = client_socket.recv(2048)
msg = filter_msg(msg)
if len(msg):
print "[ ] client> "+msg
srv_socket.send(msg)
except:
print "[-] couldn't forward message to server"
exit()
else: # srv balikin ke client
try:
msg = srv_socket.recv(2048)
if len(msg):
print "[ ] server> "+msg
client_socket.send(msg)
except:
print "[-] couldn't forward message to client"
exit()
Here’s the fun part, we can see that the message filtering happens here, so we can upgrade our filters and other security measures right here and also simultaneously have more layers of security over at our real server.
‹ Previous project: Python Simple Multiperson Chat Room | Next project: Wfhsucks › |