ayush00git commented on issue #282:
URL: https://github.com/apache/openserverless/issues/282#issuecomment-6495750429
This was the forward proxy i used (this was geenerated by claude to match a
corporate style proxy). If you want to replicate the bug with logs, run it with
`python3 corpproxy.py 172.18.0.1 3128 /tmp/corp.log`. and for live logs run -
`tail -f /tmp/corp.log`
```python
#!/usr/bin/env python3
"""HTTP proxy that imitates a corporate forward proxy, for the issue #175
reproduction.
- Logs every request (CONNECT tunnels and plain absolute-URI requests).
- REFUSES (HTTP 502) any target that resolves to a loopback address, because
a real
corporate proxy sitting elsewhere on the network cannot reach the
developer's own
machine (e.g. http://miniops.me -> 127.0.0.1). Those refusals are logged
too.
- Binds to the given address so processes inside docker/kind containers can
reach it
via the docker bridge gateway (e.g. 172.18.0.1).
Usage: python3 corpproxy.py <bind-addr> <port> <logfile>
"""
import datetime
import ipaddress
import socket
import sys
import threading
from urllib.parse import urlsplit
BIND = sys.argv[1]
PORT = int(sys.argv[2])
LOG = sys.argv[3]
lock = threading.Lock()
def log(msg):
line = f"{datetime.datetime.now().isoformat(timespec='seconds')} {msg}\n"
with lock:
with open(LOG, "a") as f:
f.write(line)
def resolves_to_loopback(host):
try:
infos = socket.getaddrinfo(host, None)
except OSError:
return False
for info in infos:
try:
if ipaddress.ip_address(info[4][0]).is_loopback:
return True
except ValueError:
pass
return host == "localhost"
def pipe(src, dst):
try:
while True:
data = src.recv(65536)
if not data:
break
dst.sendall(data)
except OSError:
pass
finally:
try:
dst.shutdown(socket.SHUT_WR)
except OSError:
pass
def handle(conn, peer):
try:
head = b""
while b"\r\n\r\n" not in head:
chunk = conn.recv(65536)
if not chunk:
return
head += chunk
first = head.split(b"\r\n", 1)[0].decode(errors="replace")
method, target, _ = first.split(" ", 2)
if method == "CONNECT":
host, port = target.rsplit(":", 1)
port = int(port)
else:
u = urlsplit(target)
host, port = u.hostname, (u.port or 80)
if host is None:
conn.sendall(b"HTTP/1.1 400 Bad Request\r\n\r\n")
return
if resolves_to_loopback(host):
log(f"REFUSED(loopback) from={peer} {method} {target}")
conn.sendall(b"HTTP/1.1 502 Bad Gateway\r\nContent-Length:
0\r\n\r\n")
return
log(f"from={peer} {method} {target}")
upstream = socket.create_connection((host, port), timeout=30)
if method == "CONNECT":
conn.sendall(b"HTTP/1.1 200 Connection Established\r\n\r\n")
else:
upstream.sendall(head)
t = threading.Thread(target=pipe, args=(upstream, conn), daemon=True)
t.start()
pipe(conn, upstream)
t.join()
except Exception as e: # noqa: BLE001
log(f"ERROR from={peer} {e!r}")
finally:
try:
conn.close()
except OSError:
pass
def main():
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind((BIND, PORT))
srv.listen(128)
log(f"LISTENING {BIND}:{PORT} (corporate-style: loopback targets
refused)")
while True:
c, addr = srv.accept()
threading.Thread(target=handle, args=(c, addr[0]),
daemon=True).start()
if __name__ == "__main__":
main()
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]