Created
January 28, 2020 13:06
-
-
Save toke/417a6c9c658d2b1617f2b72bb18426d1 to your computer and use it in GitHub Desktop.
Using TPROXY to bind to any port on many IPs (asyncio variant)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import socket | |
BIND_IP = "127.0.0.1" | |
TCP_PORT = 1234 | |
SOCK_BACKLOG = 32 | |
IP_TRANSPARENT = 19 | |
desc = f""" | |
Anybind; "bind" on many IPs and many Ports. | |
See: https://blog.cloudflare.com/how-we-built-spectrum/ | |
You may need to configure routing and TPROXY: | |
sudo ip route add local 192.168.250.0/24 dev lo src {BIND_IP} | |
sudo iptables -t mangle -I PREROUTING \ | |
-d 192.168.250.0/24 -p tcp \ | |
-j TPROXY --on-port={TCP_PORT} --on-ip={BIND_IP} | |
Needs: CAP_NET_ADMIN capability | |
""" | |
async def handle_echo(_, writer): | |
try: | |
data = b"I'm everywhere.'\n" | |
s_ip, s_port = writer.get_extra_info('peername') | |
d_ip, d_port = writer.get_extra_info('sockname') | |
print(f"Conn tcp://{s_ip}:{s_port} → tcp://{d_ip}:{d_port}") | |
writer.write(data) | |
writer.write_eof() | |
await writer.drain() | |
except ConnectionResetError: | |
print("Conn: RIP") | |
finally: | |
print("Close the client socket") | |
writer.close() | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
s.setsockopt(socket.IPPROTO_IP, IP_TRANSPARENT, 1) | |
s.bind((BIND_IP, TCP_PORT)) | |
s.listen(SOCK_BACKLOG) | |
loop = asyncio.get_event_loop() | |
coro = asyncio.start_server(handle_echo, sock=s, loop=loop) | |
server = loop.run_until_complete(coro) | |
# Serve requests until Ctrl+C is pressed | |
b_ip, b_port = server.sockets[0].getsockname() | |
print(desc) | |
print(f'Serving on tcp://{b_ip}:{b_port}') | |
try: | |
loop.run_forever() | |
except KeyboardInterrupt: | |
pass | |
print("Close server") | |
server.close() | |
loop.run_until_complete(server.wait_closed()) | |
loop.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment