| 32 | protocol_version = "HTTP/1.1" |
| 33 | |
| 34 | def do_CONNECT(self): # noqa: N802 — http.server dispatch convention |
| 35 | target = self.path |
| 36 | if target not in ALLOW: |
| 37 | sys.stderr.write(f"[egress DENY] {self.client_address[0]} → {target}\n") |
| 38 | self.send_error(403, f"egress denied: {target}") |
| 39 | return |
| 40 | host, _, port = target.rpartition(":") |
| 41 | try: |
| 42 | upstream = socket.create_connection((host, int(port)), timeout=10) |
| 43 | except OSError as e: |
| 44 | self.send_error(502, f"upstream connect failed: {e}") |
| 45 | return |
| 46 | self.send_response(200, "Connection Established") |
| 47 | self.end_headers() |
| 48 | client = self.connection |
| 49 | sys.stderr.write(f"[egress ok] {self.client_address[0]} → {target}\n") |
| 50 | self._pump(client, upstream) |
| 51 | |
| 52 | @staticmethod |
| 53 | def _pump(a: socket.socket, b: socket.socket) -> None: |