From: Michael Tremer Date: Fri, 23 Feb 2024 18:55:15 +0000 (+0000) Subject: nopaste: Remove the TCP service X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07130d5e8e0384b3f2f852cadd4579f51c922b4f;p=ipfire.org.git nopaste: Remove the TCP service Signed-off-by: Michael Tremer --- diff --git a/src/backend/nopaste.py b/src/backend/nopaste.py index e45eda72..8cc462f2 100644 --- a/src/backend/nopaste.py +++ b/src/backend/nopaste.py @@ -257,211 +257,3 @@ class Paste(Object): id = %s """, self.id, ) - - -# PROXY Protocol Implementation -PROXY_CMD_LOCAL = 0 -PROXY_CMD_PROXY = 1 - -PROXY_FAMILY_UNSPEC = 0 -PROXY_FAMILY_INET = 1 -PROXY_FAMILY_INET6 = 2 - -PROXY_PROTO_UNSPEC = 0 -PROXY_PROTO_STREAM = 1 -PROXY_PROTO_DGRAM = 2 - -class ProxyError(Exception): - pass - - -class ProxyUnsupportedError(ProxyError): - pass - - -class Service(tornado.tcpserver.TCPServer): - def __init__(self, config, use_proxy=True, **kwargs): - # Initialize backend - self.backend = base.Backend(config) - - # Expect PROXY headers? - self.use_proxy = use_proxy - - super().__init__(**kwargs) - - async def handle_stream(self, stream, address): - buffer = io.BytesIO() - - # Parse the PROXY header - if self.use_proxy: - try: - address = await self._parse_proxyv2_header(stream, address) - - # Close the stream on any proxy errors - except ProxyError as e: - log.error("Proxy Error: %s" % e) - - return stream.close() - - # If we received no result, this connection is not supposed to be relayed - if not address: - return - - # Read the entire stream - try: - while True: - chunk = await stream.read_bytes(CHUNK_SIZE, partial=True) - - log.debug("Read a chunk of %s byte(s)" % len(chunk)) - - # Write the chunk into the buffer - buffer.write(chunk) - - # If we have read less then we have reached the end - if len(chunk) < CHUNK_SIZE: - break - - # End if the stream closed unexpectedly - except tornado.iostream.StreamClosedError as e: - return - - log.debug("Finished reading payload") - - # Process address - address, port = address - - # Store this into the database - with self.backend.db.transaction(): - paste = self.backend.nopaste.create( - buffer.getvalue(), - subject="Streamed Upload", - address=address, - ) - - # Format a response message - message = "https://nopaste.ipfire.org/view/%s\n" % paste.uuid - - # Send the message - await stream.write(message.encode("utf-8")) - - # We are done, close the stream - stream.close() - - async def _parse_proxyv2_header(self, stream, address): - """ - Parses the PROXYv2 header and returns the real client's IP address - """ - src_address, src_port, dst_address, dst_port = None, None, None, None - - log.debug("Parsing PROXY connection from %s:%s" % address) - - # Header - proxy_hdr_v2 = struct.Struct("!12BBBH") - proxy_addr_v6 = struct.Struct("!16B16BHH") - proxy_addr_v4 = struct.Struct("!IIHH") - - # Try to read the header into a buffer - buffer = await stream.read_bytes(proxy_hdr_v2.size) - - if len(buffer) < proxy_hdr_v2.size: - raise ProxyError("Header too short") - - # Parse the header - *signature, ver_cmd, fam_prot, length = proxy_hdr_v2.unpack(buffer) - - # Check signature - if not signature == [13, 10, 13, 10, 0, 13, 10, 81, 85, 73, 84, 10]: - raise ProxyError("Incorrect signature") - - # Extract version and command - version = (ver_cmd >> 4) - command = (ver_cmd & 0x0f) - - # Check protocol version - if not version == 2: - raise ProxyError("Incorrect protocol version") - - # Handle LOCAL commands - if command == PROXY_CMD_LOCAL: - pass - - # Handle PROXY commands - elif command == PROXY_CMD_PROXY: - pass # Fallthrough - - # We don't know any other commands - else: - log.debug("Unknown PROXY command %02x" % command) - return - - # Extract protocol - family = (fam_prot >> 4) - protocol = (fam_prot & 0x0f) - - # LOCAL command use family == AF_UNSPEC - if command == PROXY_CMD_LOCAL and family == PROXY_FAMILY_UNSPEC: - pass - - # We accept IPv6 and IPv4 - elif family in (PROXY_FAMILY_INET6, PROXY_FAMILY_INET): - pass - - # Everything else we don't know how to handle here - else: - raise ProxyError("Unknown family %s" % family) - - # LOCAL commands use protocol == UNSPEC - if command == PROXY_CMD_LOCAL and protocol == PROXY_PROTO_UNSPEC: - pass - - # Otherwise we only support TCP - elif protocol == PROXY_PROTO_STREAM: - pass - - # We don't know how to handle anything else here - else: - raise ProxyUnsupportedError("Unknown or unsupported protocol %s" % protocol) - - # Read the next part of the header into the buffer - buffer = await stream.read_bytes(length) - - # Check if we read enough data - if len(buffer) < length: - raise ProxyError("Header too short") - - # Unpack IPv6 addresses - if family == PROXY_FAMILY_INET6: - addresses = proxy_addr_v6.unpack(buffer[:proxy_addr_v6.size]) - - src_address = ipaddress.IPv6Address(bytes(addresses[:16])) - src_port = addresses[-2] - dst_address = ipaddress.IPv6Address(bytes(addresses[16:32])) - dst_port = addresses[-1] - - # Truncate buffer - buffer = buffer[proxy_addr_v6.size:] - - # Unpack IPv4 addresses - elif family == PROXY_FAMILY_INET: - src_address, dst_address, src_port, dst_port = proxy_addr_v4.unpack( - buffer[:proxy_addr_v4.size], - ) - - # Convert IP addresses - src_address = ipaddress.IPv4Address(src_address) - dst_address = ipaddress.IPv4Address(dst_address) - - # Truncate buffer - buffer = buffer[proxy_addr_v4.size:] - - # Handle UNSPEC - elif family == PROXY_FAMILY_UNSPEC: - pass - - # Log the result - if src_address and dst_address: - log.debug("Accepted new connection from %s:%s to %s:%s" \ - % (src_address, src_port, dst_address, dst_port)) - - # Return the source address - return "%s" % src_address, src_port diff --git a/src/scripts/ipfire.org-webapp.in b/src/scripts/ipfire.org-webapp.in index 86a7b1d3..6c57ecf2 100755 --- a/src/scripts/ipfire.org-webapp.in +++ b/src/scripts/ipfire.org-webapp.in @@ -17,10 +17,6 @@ async def run(): debug=tornado.options.options.debug) app.listen(tornado.options.options.port, xheaders=True) - # Initialize the nopaste service - nopaste = ipfire.nopaste.Service("@configsdir@/@PACKAGE_NAME@.conf") - nopaste.listen(tornado.options.options.port + 1000) - # Wait for forever await asyncio.Event().wait()