{"id":18451503,"url":"https://github.com/scotow/goxy","last_synced_at":"2025-08-22T22:45:44.234Z","repository":{"id":86942378,"uuid":"153916050","full_name":"scotow/goxy","owner":"scotow","description":"TCP tunnel over HTTP","archived":false,"fork":false,"pushed_at":"2019-02-01T14:24:27.000Z","size":93,"stargazers_count":6,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-06-21T18:07:08.656Z","etag":null,"topics":["go","golang","http","proxy","proxy-server","ssh","tcp"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scotow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-20T14:50:09.000Z","updated_at":"2020-12-24T19:51:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"02f21751-d26b-40bd-8e22-55ec521c7f5b","html_url":"https://github.com/scotow/goxy","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scotow%2Fgoxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scotow%2Fgoxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scotow%2Fgoxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scotow%2Fgoxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scotow","download_url":"https://codeload.github.com/scotow/goxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223300086,"owners_count":17122512,"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":["go","golang","http","proxy","proxy-server","ssh","tcp"],"created_at":"2024-11-06T07:28:51.859Z","updated_at":"2024-11-06T07:28:52.059Z","avatar_url":"https://github.com/scotow.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# goxy - A TCP tunnel over HTTP\n\n### ⚠️ This project was made for an university (TIIR - Lille) coursework and should not be considered has a serious project, nor used for production. Some features may not be implemented too. ⚠️\n\n\n## Bonus Features\n\n* Allow multiple TCP connections to the same remote host.\n* Local TCP and HTTP ports are customizable.\n* Remote TCP and HTTP ports are customizable too.\n\n\n## Obfuscation methods\n\n### Random path (URI)\n\nIn order to allow multiple connections from the same client to the same remote Goxy server, an ID has to be passed to each HTTP request to allow the server to redirect the content to the correct server-side TCP connection.\n\nWhen establishing a new connection between a Goxy client and a Goxy server, a handshake is made. The client asks for a id to the server, and the server return an unused id. This id is an array of at least three (classic) alphabetic letters.\n\nThen, for each following request initiated, the client picks for each letter in the id, a random word highly used in the english language having its second to last letter equal to this letter.\n\nThese words are then joined with a '/' and used as an URI.\n\nExample:\n\nIf the id given by the server is 'ALY', the client may make a request using the following URL: \n\n```text\n'http://remoteserver.com/local/world/plays'\n                            ^     ^     ^\n                            A     L     Y\n```\n\n\n### Hide in common files \n\nTo bypass proxies that try to detect the content type of files downloaded (or uploaded) to a server, each request append a random file extension to the URI (ie. '.png').\n\nThen, depending on the file extension presents in the URI, the server adds the magic bytes corresponding to the file type at the start of the response body.\n\nThe 'Content-Type' HTTP header of the response is set to the corresponding mime-type.\n\nExample:\n\nIf the request URI is '/local/world/plays.png', the response body will looks like this: \n\n```text\nx89 x50 x4E x47 x0D x0A x1A x0A .. .. .. .. .. .. ..\n\\_______PNG Format magic______/ \\__Useful_data_____/\n\n```\n\nWhen receiving a response, the client detect the file extension and ignore the N first bytes of the response. \n\n\n### Prioritize GET over POST\n\nWhile browsing the web, the average ratio of GET requests vs the number of POST requests is more/less of 90% GET and 10% POST.\n\nAssuming that an SSH connection write the same amount of data it reads from the TCP connection, making 50% POST and 50% GET may be a bad idea.\n\nWhile inspecting the content length of the TCP packets while using SSH, packets size rarely exceed 128 bytes.\n\nEncoding the content of client output data in base64 and putting this encoded data in a commonly used HTTP header allows the ratio of GET/POST request to be 95% GET for 5% POST requests. \n\n\n### Encode content\n\nTo prevent classic (but useful) string matching (like the SSH handshake header) all the content is encoded as base64.\n\n\n### Long polling\n\nTo prevent unnecessary request to know if the server as available data, the server uses long polling. Doing so, if the user do not touch his terminal, no request should be completed (except some SSH heartbeats).\n\n\n### Using OTP\n\nIn order to prevent the server from asking data to the server, while the client did not ask for it, the server gives an OTP (One Time Password) for the next read and another one for the next write.\n\nIf the server receives a request with an invalid OTP, the server response with a useless 200 response so the proxy doesn't notice a mismatch in the status code.\n\n\n### Use common User-Agents\n\nTo prevent proxy that blocks request based on the user agent of the request, a Google Chrome or Firefox user agent is set for each request.\n\n\n## Building and starting the server and the client\n\n### Installing\n\nGolang 1.11.2 was used to make this project.\n\nBe sure to have set your GOPATH variable.\n\n```sh\nmkdir -p $GOPATH/src/github.com/scotow\ncp goxy $GOPATH/src/github.com/scotow/\n```\n\n\n### Running the server\n\n```sh\ngo run $GOPATH/src/github.com/scotow/goxy/cmd/goxys/main.go\n```\n\nUse the `-h` options to change the default parameters\n\n\n### Running the client\n\n```sh\ngo run $GOPATH/src/github.com/scotow/goxy/cmd/goxyc/main.go\n\n```\n\nUse the `-h` options to change the default parameters\n\n\n### SSH examples\n\nSimple SSH connections\n\n```sh\nssh -p 2222 localhost\n```\n\nSSH Reverse tunnel option can be used to connect from home to the company's computer\n\n```sh\nssh -p 2222 -R 2222:localhost:22 my.home.com\n```\n\nThen while at home\n\n```sh\nssh -p 2222 localhost\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscotow%2Fgoxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscotow%2Fgoxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscotow%2Fgoxy/lists"}