Package: siosocks
siosocks[(https://github.com/pohmelie/siosocks/actions)Sans-iosocks 4/5 client/server library/framework.ReasonsNo one-shot socks serversSans-ioasyncio-readytwunnel3is deadaiosocksdo not mimicasyncio.open_connectionarguments (maybe dead too)FunFeaturesOnly tcp connect (no bind, no udp)Both client and serverSocks versions: 4, 4a, 5Socks5 auth: no auth, username/passwordCouple io backends: asyncio, trio, socketserverOne-shot socks server (python -m siosocks)Licensesiosocksis offered under MIT license.Requirementspython 3.8+IO implementation matrixFrameworkClientServerasyncio++trio++socket+Feel free to make it bigger :wink:UsageEnd user implementations mimic «parent» library api.Clientasyncio:open_connectiontrio:open_tcp_streamExtra keyword-only arguments:socks_host: stringsocks_port: integersocks_version: integer (4 or 5)username: optional string (default:None)password: optional string (default:None)encoding: optional string (default:"utf-8")socks4_extras: optional dictionarysocks5_extras: optional dictionaryExtras:socks4user_id: string (default:"")socks5None at this moment, added for uniform apiServerEnd user implementations mimic «parent» library server request handlers.asyncio:start_servertrio:serve_tcpsocketserver:ThreadingTCPServerYou should usepartialto bind socks specific arguments:allowed_versions: set of integers (default:{4, 5})username: optional string (default:None)password: optional string (default:None)strict_security_policy: boolean, ifTrueexception will be raised if authentication required and 4 is in allowed versions set (default:True)encoding: optional string (default:"utf-8")Nothing to say more. Typical usage can be found at__main__.pyExamplesHigh-levelThis section will useasyncioas backend, since it is main target/reason forsiosocksClientimportasynciofromsiosocks.io.asyncioimportopen_connectionHOST="api.ipify.org"REQ="""GET /?format=json HTTP/1.1Host: api.ipify.orgUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en,en-US;q=0.7,ru;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: keep-aliveUpgrade-Insecure-Requests: 1Cache-Control: max-age=0"""asyncdefmain():# assume we have tor startedr,w=awaitopen_connection(HOST,80,socks_host="localhost",socks_port=9050,socks_version=5)w.write(REQ.replace("\n","\r\n").encode())awaitw.drain()print(awaitr.read(8192))w.close()loop=asyncio.get_event_loop()loop.run_until_complete(main())Serverimportsocketimportasyncioimportcontextlibfromsiosocks.io.asyncioimportsocks_server_handlerloop=asyncio.get_event_loop()server=loop.run_until_complete(asyncio.start_server(socks_server_handler,port=1080))addresses=[]forsockinserver.sockets:ifsock.familyin(socket.AF_INET,socket.AF_INET6):host,port,*_=sock.getsockname()addresses.append(f"{host}:{port}")print(f"Socks4/5 proxy serving on{', '.join(addresses)}")withcontextlib.suppress(KeyboardInterrupt):loop.run_forever()But if you just want one-shot socks server then try:python-msiosocksThis will start socks 4, 5 server on all interfaces on 1080 port. For more information try--helppython-msiosocks--help
usage:siosocks[-h][--backend{asyncio,socketserver,trio}][--hostHOST][--portPORT][--family{ipv4,ipv6,auto}][--socksSOCKS][--usernameUSERNAME][--passwordPASSWORD][--encodingENCODING][--no-strict][-v]Socksproxyserver

optionalarguments:-h,--helpshowthishelpmessageandexit--backend{asyncio,socketserver,trio}Socksserverbackend[default:asyncio]--hostHOSTSocksserverhost[default:None]--portPORTSocksserverport[default:1080]--family{ipv4,ipv6,auto}Socketfamily[default:auto]--socksSOCKSSocksprotocolversion[default:[]]--usernameUSERNAMESocksauthusername[default:None]--passwordPASSWORDSocksauthpassword[default:None]--encodingENCODINGStringencoding[default:utf-8]--no-strictAllowmultiversionsocksserver,whensocks5usedwithusername/passwordauth[default:False]-v,--versionShowsiosocksversionExceptionssiosockshave unified exception for all types of socks-related errors:importasynciofromsiosocks.exceptionsimportSocksExceptionfromsiosocks.io.asyncioimportopen_connectionasyncdefmain():try:r,w=awaitopen_connection("127.0.0.1",80,socks_host="localhost",socks_port=9050,socks_version=5)exceptSocksException:...else:# at this point all socks-related tasks done and returned reader and writer# are just plain asyncio objects without any siosocks proxiesloop=asyncio.get_event_loop()loop.run_until_complete(main())Low-levelShadowsocks-likeclient/server. Shadowsocks-like built on top of socks5 and encryption. It have «client», which is actually socks server and «server». So, precisely there are two servers: client side and server side. Purpose of shadowsocks is to encrypt data between «incoming» and «outgoing» servers. In common this looks like:client (non-encrypted socks) «incoming» socks server (encrypted socks) «outgoing» socks server (non-socks connection) target serverExample above use Caesar cipher for simplicity (and security of course).Roadmap/contibutionsadd more backends (average)speed uppassthroughimplementation (seems hard)add client redirection