{"id":13775773,"url":"https://github.com/ickerwx/tcpproxy","last_synced_at":"2025-05-11T08:33:22.865Z","repository":{"id":28740558,"uuid":"32262026","full_name":"ickerwx/tcpproxy","owner":"ickerwx","description":"Intercepting TCP proxy to modify raw TCP streams using modules on incoming or outgoing traffic","archived":false,"fork":false,"pushed_at":"2023-08-24T18:52:12.000Z","size":753,"stargazers_count":278,"open_issues_count":3,"forks_count":85,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-01-28T02:38:13.651Z","etag":null,"topics":["module-system","penetration-testing","python","reverse-engineering","tcpproxy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ickerwx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-03-15T13:32:05.000Z","updated_at":"2024-01-13T23:53:31.000Z","dependencies_parsed_at":"2024-01-07T22:45:14.192Z","dependency_job_id":"59951d27-df6e-4d6d-8735-4f6bda165fa1","html_url":"https://github.com/ickerwx/tcpproxy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ickerwx%2Ftcpproxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ickerwx%2Ftcpproxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ickerwx%2Ftcpproxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ickerwx%2Ftcpproxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ickerwx","download_url":"https://codeload.github.com/ickerwx/tcpproxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253540331,"owners_count":21924521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["module-system","penetration-testing","python","reverse-engineering","tcpproxy"],"created_at":"2024-08-03T17:01:49.358Z","updated_at":"2025-05-11T08:33:22.591Z","avatar_url":"https://github.com/ickerwx.png","language":"Python","funding_links":[],"categories":["\u003ca id=\"d03d494700077f6a65092985c06bf8e8\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"0ff94312f3ab4898f5996725133ea9d1\"\u003e\u003c/a\u003e未分类"],"readme":"# tcpproxy.py - An intercepting proxy for TCP data\n\nThis tool opens a listening socket, receives data and then runs this data through a chain of proxy modules. After the modules are done, the resulting data is sent to the target server. The response is received and again run through a chain of modules before sending the final data back to the client.\nTo intercept the data, you will either have to be the gateway or do some kind of man-in-the-middle attack. Set up iptables so that the PREROUTING chain will modify the destination and send it to the proxy process. The proxy will then send the data on to whatever target was specified.\n\nThis tool is inspired by and partially based on the TCP proxy example used in Justin Seitz' book \"Black Hat Python\" by no starch press.\n\n## Usage\n\n```\n$ ./tcpproxy.py -h\nusage: tcpproxy.py [-h] [-ti TARGET_IP] [-tp TARGET_PORT] [-li LISTEN_IP]\n                   [-lp LISTEN_PORT] [-pi PROXY_IP] [-pp PROXY_PORT]\n                   [-pt {SOCKS4,SOCKS5,HTTP}] [-om OUT_MODULES]\n                   [-im IN_MODULES] [-v] [-n] [-l LOGFILE] [--list]\n                   [-lo HELP_MODULES] [-s] [-sc SERVER_CERTIFICATE]\n                   [-sk SERVER_KEY] [-cc CLIENT_CERTIFICATE] [-ck CLIENT_KEY]\n\nSimple TCP proxy for data interception and modification. Select modules to\nhandle the intercepted traffic.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -ti TARGET_IP, --targetip TARGET_IP\n                        remote target IP or host name\n  -tp TARGET_PORT, --targetport TARGET_PORT\n                        remote target port\n  -li LISTEN_IP, --listenip LISTEN_IP\n                        IP address/host name to listen for incoming data\n  -lp LISTEN_PORT, --listenport LISTEN_PORT\n                        port to listen on\n  -pi PROXY_IP, --proxy-ip PROXY_IP\n                        IP address/host name of proxy\n  -pp PROXY_PORT, --proxy-port PROXY_PORT\n                        proxy port\n  -pt {SOCKS4,SOCKS5,HTTP}, --proxy-type {SOCKS4,SOCKS5,HTTP}\n                        proxy type. Options are SOCKS5 (default), SOCKS4, HTTP\n  -om OUT_MODULES, --outmodules OUT_MODULES\n                        comma-separated list of modules to modify data before\n                        sending to remote target.\n  -im IN_MODULES, --inmodules IN_MODULES\n                        comma-separated list of modules to modify data\n                        received from the remote target.\n  -v, --verbose         More verbose output of status information\n  -n, --no-chain        Don't send output from one module to the next one\n  -l LOGFILE, --log LOGFILE\n                        Log all data to a file before modules are run.\n  --list                list available modules\n  -lo HELP_MODULES, --list-options HELP_MODULES\n                        Print help of selected module\n  -s, --ssl             detect SSL/TLS as well as STARTTLS\n  -sc SERVER_CERTIFICATE, --server-certificate SERVER_CERTIFICATE\n                        server certificate in PEM format (default: mitm.pem)\n  -sk SERVER_KEY, --server-key SERVER_KEY\n                        server key in PEM format (default: mitm.pem)\n  -cc CLIENT_CERTIFICATE, --client-certificate CLIENT_CERTIFICATE\n                        client certificate in PEM format in case client\n                        authentication is required by the target\n  -ck CLIENT_KEY, --client-key CLIENT_KEY\n                        client key in PEM format in case client authentication\n                        is required by the target\n```\n\nYou will have to  provide TARGET_IP and TARGET_PORT, the default listening settings are 0.0.0.0:8080. To make the program actually useful, you will have to decide which modules you want to use on outgoing (client to server) and incoming (server to client) traffic. You can use different modules for each direction. Pass the list of modules as comma-separated list, e.g. -im mod1,mod4,mod2. The data will be passed to the first module, the returned data will be passed to the second module and so on, unless you use the -n/--no/chain switch. In that case, every module will receive the original data.\nYou can also pass options to each module: -im mod1:key1=val1,mod4,mod2:key1=val1:key2=val2. To learn which options you can pass to a module use -lo/--list-options like this: -lo mod1,mod2,mod4\n\n## Modules\n\n```\n$ ./tcpproxy.py --list\ndigestdowngrade - Find HTTP Digest Authentication and replace it with a Basic Auth\nhexdump - Print a hexdump of the received data\nhttp_ok - Prepend HTTP response header\nhttp_post - Prepend HTTP header\nhttp_strip - Remove HTTP header from data\nlog - Log data in the module chain. Use in addition to general logging (-l/--log).\nremovegzip - Replace gzip in the list of accepted encodings in a HTTP request with booo.\nreplace - Replace text on the fly by using regular expressions in a file or as module parameters\nhexreplace - Replace hex data in tcp packets\nsize - Print the size of the data passed to the module\nsize404 - Change HTTP responses of a certain size to 404.\ntextdump - Simply print the received data as text\n```\n\nTcpproxy.py uses modules to view or modify the intercepted data. To see the possibly easiest implementation of a module, have a look at the textdump.py module in the proxymodules directory:\n\n```python\n#!/usr/bin/env python3\nimport os.path as path\n\n\nclass Module:\n    def __init__(self, incoming=False, verbose=False, options=None):\n        # extract the file name from __file__. __file__ is proxymodules/name.py\n        self.name = path.splitext(path.basename(__file__))[0]\n        self.description = 'Simply print the received data as text'\n        self.incoming = incoming  # incoming means module is on -im chain\n        self.find = None  # if find is not None, this text will be highlighted\n        if options is not None:\n            if 'find' in options.keys():\n                self.find = bytes(options['find'], 'ascii')  # text to highlight\n            if 'color' in options.keys():\n                self.color = bytes('\\033[' + options['color'] + 'm', 'ascii')  # highlight color\n            else:\n                self.color = b'\\033[31;1m'\n\n    def execute(self, data):\n        if self.find is None:\n            print(data)\n        else:\n            pdata = data.replace(self.find, self.color + self.find + b'\\033[0m')\n            print(pdata.decode('ascii'))\n        return data\n\n    def help(self):\n        h = '\\tfind: string that should be highlighted\\n'\n        h += ('\\tcolor: ANSI color code. Will be wrapped with \\\\033[ and m, so'\n              ' passing 32;1 will result in \\\\033[32;1m (bright green)')\n        return h\n\n\nif __name__ == '__main__':\n    print('This module is not supposed to be executed alone!')\n```\n\nEvery module file contains a class named Module. Every module MUST set self.description and MUST implement an execute method that accepts one parameter, the input data. The execute method MUST return something, this something is then either passed to the next module or sent on. Other than that, you are free to do whatever you want inside a module.\nThe incoming parameter in the constructor is set to True when the module is in the incoming chain (-im), otherwise it's False. This way, a module knows in which direction the data is flowing (credits to jbarg for this idea).\nThe verbose parameter is set to True if the proxy is started with -v/--verbose.\nThe options parameter is a dictionary with the keys and values passed to the module on the command line. Note that if you use the options dictionary in your module, you should also implement a help() method. This method must return a string. Use one line per option, make sure each line starts with a \\t character for proper indentation.\n\nSee the hexdump module for an additional options example:\n\n```python\n#!/usr/bin/env python3\nimport os.path as path\n\n\nclass Module:\n    def __init__(self, incoming=False, verbose=False, options=None):\n        # extract the file name from __file__. __file__ is proxymodules/name.py\n        self.name = path.splitext(path.basename(__file__))[0]\n        self.description = 'Print a hexdump of the received data'\n        self.incoming = incoming  # incoming means module is on -im chain\n        self.len = 16\n        if options is not None:\n            if 'length' in options.keys():\n                self.len = int(options['length'])\n\n    def help(self):\n        return '\\tlength: bytes per line (int)'\n\n    def execute(self, data):\n        # -- 8\u003c --- snip\n        for i in range(0, len(data), self.len):\n            s = data[i:i + self.len]\n        # # -- 8\u003c --- snip\n\nif __name__ == '__main__':\n    print 'This module is not supposed to be executed alone!'\n```\n\nThe above example should give you an idea how to make use of module parameters. A calling example would be:\n\n```\n./tcpproxy.py -om hexdump:length=8,http_post,hexdump:length=12 -ti 127.0.0.1 -tp 12345\n\u003c \u003c \u003c \u003c out: hexdump\n0000   77 6C 6B 66 6A 6C 77 71    wlkfjlwq\n0008   6B 66 6A 68 6C 6B 77 71    kfjhlkwq\n0010   6A 65 68 66 6C 6B 65 77    jehflkew\n0018   71 6A 66 68 6C 6B 65 77    qjfhlkew\n0020   71 6A 66 68 6C 6B 65 77    qjfhlkew\n0028   71 6A 66 6C 68 77 71 6B    qjflhwqk\n0030   65 6A 66 68 77 71 6C 6B    ejfhwqlk\n0038   65 6A 66 68 0A             ejfh.\n\u003c \u003c \u003c \u003c out: http_post\n\u003c \u003c \u003c \u003c out: hexdump\n0000   50 4F 53 54 20 2F 20 48 54 54 50 2F    POST / HTTP/\n000C   31 2E 31 0A 48 6F 73 74 3A 20 74 63    1.1.Host: tc\n0018   70 70 72 6F 78 79 0A 43 6F 6E 74 65    pproxy.Conte\n0024   6E 74 2D 4C 65 6E 67 74 68 3A 20 36    nt-Length: 6\n0030   31 0A 0A 77 6C 6B 66 6A 6C 77 71 6B    1..wlkfjlwqk\n003C   66 6A 68 6C 6B 77 71 6A 65 68 66 6C    fjhlkwqjehfl\n0048   6B 65 77 71 6A 66 68 6C 6B 65 77 71    kewqjfhlkewq\n0054   6A 66 68 6C 6B 65 77 71 6A 66 6C 68    jfhlkewqjflh\n0060   77 71 6B 65 6A 66 68 77 71 6C 6B 65    wqkejfhwqlke\n006C   6A 66 68 0A                            jfh.\n```\n\nYou can see how the first hexdump instance gets a length of 8 bytes per row and the second instance gets a length of 12 bytes. To pass more than one option to a single module, seperate the options with a : character, modname:key1=val1:key2=val2...\n\n## Logging\n\nYou can write all data that is sent or received by the proxy to a file using the -l/--log \u003cfilename\u003e parameter. Data (and some housekeeping info) is written to the log before passing it to the module chains. If you want to log the state of the data during or after the modules are run, you can use the log proxymodule. Using the chain -im http_post,log:file=log.1,http_strip,log would first log the data after the http_post module to the logfile with the name log.1. The second use of the log module at the end of the chain would write the final state of the data to a logfile with the default name in-\u003ctimestamp\u003e right before passing it on .\n\n## TODO\n\n- [ ] make the process interactive by implementing some kind of editor module (will probably complicate matters with regard to timeouts, can be done for now by using the burp solution detailed above and modifying data inside burp)\n- [ ] Create and maintain a parallel branch that is compatible with jython but also has most of the new stuff introduced after e3290261\n\n## Contributions\n\nI want to thank the following people for spending their valuable time and energy on improving this little tool:\n\n- [Adrian Vollmer](https://github.com/AdrianVollmer)\n- [Michael Füllbier](https://github.com/mfuellbier)\n- [Stefan Grönke](https://github.com/gronke)\n- [Mattia](https://github.com/sowdust)\n- [bjorns163](https://github.com/bjorns163)\n- [Pernat1y](https://github.com/Pernat1y)\n- [hrzlgnm](https://github.com/hrzlgnm)\n- [MKesenheimer](https://github.com/MKesenheimer)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fickerwx%2Ftcpproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fickerwx%2Ftcpproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fickerwx%2Ftcpproxy/lists"}