{"id":26600804,"url":"https://github.com/enthus1ast/nimsocks","last_synced_at":"2025-04-09T16:24:09.663Z","repository":{"id":43650478,"uuid":"107249588","full_name":"enthus1ast/nimSocks","owner":"enthus1ast","description":" A filtering SOCKS proxy server and client library written in nim. ","archived":false,"fork":false,"pushed_at":"2023-02-10T21:56:05.000Z","size":130,"stargazers_count":62,"open_issues_count":5,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T04:44:20.207Z","etag":null,"topics":["filter","filtering","nim","nim-lang","proxy","proxy-client","proxy-server","socks","socks-proxy","socks4","socks4a","socks5"],"latest_commit_sha":null,"homepage":"","language":"Nim","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/enthus1ast.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}},"created_at":"2017-10-17T09:51:52.000Z","updated_at":"2025-02-12T17:18:15.000Z","dependencies_parsed_at":"2023-01-19T06:45:23.321Z","dependency_job_id":null,"html_url":"https://github.com/enthus1ast/nimSocks","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/enthus1ast%2FnimSocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enthus1ast%2FnimSocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enthus1ast%2FnimSocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enthus1ast%2FnimSocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enthus1ast","download_url":"https://codeload.github.com/enthus1ast/nimSocks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245152065,"owners_count":20569368,"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":["filter","filtering","nim","nim-lang","proxy","proxy-client","proxy-server","socks","socks-proxy","socks4","socks4a","socks5"],"created_at":"2025-03-23T18:35:29.530Z","updated_at":"2025-03-23T18:35:32.206Z","avatar_url":"https://github.com/enthus1ast.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nimSocks\na filtering (standalone) SOCKS proxy server and client library for nim.\n\n## Features client and server\n- (SOCKS4, SOCKS4a server only), SOCKS5 \n- password auth / no auth\n- ipv4, ipv6, domain.\n- SOCKS CONNECT (no bind, no udp atm)\n- domain target white/black-listing\n- static hosts\n\n## SOCKS Compatibility Table\n\n| Socks Version | TCP | UDP | IPv4 | IPv6 | Hostname |\n| --- | :---: | :---: | :---: | :---: | :---: |\n| SOCKS v4 | ✅ | ❌ | ✅ | ❌ | ❌ |\n| SOCKS v4a | ✅ | ❌ | ✅ | ❌ | ✅ |\n| SOCKS v5 | ✅ | ✅ | ✅ | ✅ | ✅ |\n\n## nimSocks implementation\n| lib | TCP connect | TCP accociate | UDP bind |\n| --- | :---: | :---: | :---: |\n|server | ✅ | ❌ | ❌ |\n|client | ✅ | ❌ | ❌ |\n\n| lib | SOCKS v4 | SOCKS v4a | SOCKS v5 |\n| --- | :---: | :---: | :---: |\n|server | ✅ | ✅ | ✅ |\n|client | ❌ | ❌ | ✅ |\n\n| auth | no auth | user/password |\n| --- | :---: | :---: |\n|server | ✅ | ✅ |\n|client | ✅ | ✅ |\n\n\n# server\n## usage\n\n```nim\n  import nimSocks/server\n  var proxy = newSocksServer()\n  echo \"SOCKS Proxy listens on: \", proxy.listenPort\n  proxy.allowedSocksVersions = {SOCKS_V4, SOCKS_V5}\n  proxy.allowedAuthMethods = {USERNAME_PASSWORD, NO_AUTHENTICATION_REQUIRED}\n\n  ## Add a valid user / password combination\n  proxy.addUser(\"hans\", \"peter\")\n\n  ## For a static host replacement:\n  proxy.staticHosts.add(\"peter.peter\", \"example.org\")\n\n  asyncCheck proxy.serve()\n  asyncCheck proxy.dumpThroughput()\n  runForever()\n```\n\n## black and whitelisting example filter file \n(full domain match only)\n\nfor a good blacklist file use\nhttps://raw.githubusercontent.com/notracking/hosts-blocklists/master/dnscrypt-proxy/dnscrypt-proxy.blacklist.txt\n\nfiles \n- whitelist.txt\n- blacklist.txt\n\n\n```\nnim-lang.org\nforum.nim-lang.org\n```\n\n\n## example \"fancy\" filter \n\nfiles \n- whitelistFancy.txt\n- blacklistFancy.txt\n\n\n```\n\n# '#' is a comment\n\n# all domains containing nim\ncon nim\n\n# ending with\nend nim-lang.org\nend wikipedia.org\n\n# exact match\neql github.org\n\n# startswith\nsta foo.baa\n```\n\nif there are whitelist* entries\nthe blacklist* gets skipped!\n\n\n## static hosts\nfill the `staticHosts` table to always resolve to given ip/dns\n\n```nim\n#...\nproxy.staticHosts.add(\"foo.loc\", \"example.org\")\nproxy.staticHosts.add(\"baa.loc\", \"192.168.1.1\")\n#...\n```\n\n# client\nthe client can \"upgrade\" your socket.\n\n```nim\nvar sock = waitFor asyncnet.dial(\"127.0.0.1\", Port 1080 ) # dial to the socks server \nassert true == waitFor sock.doSocksHandshake(\n    username=\"username\", \n    password=\"password\", \n    methods={NO_AUTHENTICATION_REQUIRED, USERNAME_PASSWORD} # the \"best\" auth supported gets choosen by the server!\n    ) \nassert true == waitFor sock.doSocksConnect(\"example.org\", Port 80) # instruct the proxy to connect to target host (by tcp)\n\n# Then do normal socket operations\nsock.send(\"FOO\")\n```\n\n## proxy hopping\nyou could easily do \"proxy hopping\", \nby letting the first SOCKS server connect to the next,\nthen do handshake, connect, etc.\n\n\n```nim\nvar sock = waitFor asyncnet.dial(\"firstSocks.loc\", Port 1080 )\nassert true == waitFor sock.doSocksHandshake(methods={NO_AUTHENTICATION_REQUIRED})\nassert true == waitFor sock.doSocksConnect(\"secondSocks.loc\", Port 1080) \n\nassert true == waitFor sock.doSocksHandshake(methods={NO_AUTHENTICATION_REQUIRED})\nassert true == waitFor sock.doSocksConnect(\"mytarget.loc\", Port 80) \n\nsock.send(\"FOO\") # from here we speak to \"mytarget.loc\"\nsock.close() # will destroy the whole tunnel\n```\n \n## random examples\n```\n$ ncat --proxy 127.0.0.1:1080 --proxy-type socks5 --proxy-auth hans:peter  2a02:bbb:aaa:9daa:ff11:a4ff:aaaa:bbbb 9090\n$ curl --socks5-basic --socks5 hans:peter@127.0.0.1:1080 google.de\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenthus1ast%2Fnimsocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenthus1ast%2Fnimsocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenthus1ast%2Fnimsocks/lists"}