用Python写socks5服务器端

参考自RFC1928: http://xiaoxia.org/?p=2672

直接运行这个程序就给本机建立了一个socks5的代理服务器。

代码如下:

import socket, sys, select, SocketServer, struct, time

class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass
class Socks5Server(SocketServer.StreamRequestHandler):
    def handle_tcp(self, sock, remote):
        fdset = [sock, remote]
        while True:
            r, w, e = select.select(fdset, [], [])
            if sock in r:
                if remote.send(sock.recv(4096)) <= 0: break
            if remote in r:
                if sock.send(remote.recv(4096)) <= 0: break
    def handle(self):
        try:
            print 'socks connection from ', self.client_address
            sock = self.connection
            # 1. Version
            sock.recv(262)
            sock.send(b"\x05\x00");
            # 2. Request
            data = self.rfile.read(4)
            mode = ord(data[1])
            addrtype = ord(data[3])
            if addrtype == 1:       # IPv4
                addr = socket.inet_ntoa(self.rfile.read(4))
            elif addrtype == 3:     # Domain name
                addr = self.rfile.read(ord(sock.recv(1)[0]))
            port = struct.unpack('>H', self.rfile.read(2))
            reply = b"\x05\x00\x00\x01"
            try:
                if mode == 1:  # 1. Tcp connect
                    remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    remote.connect((addr, port[0]))
                    print 'Tcp connect to', addr, port[0]
                else:
                    reply = b"\x05\x07\x00\x01" # Command not supported
                local = remote.getsockname()
                reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1])
            except socket.error:
                # Connection refused
                reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00'
            sock.send(reply)
            # 3. Transfering
            if reply[1] == '\x00':  # Success
                if mode == 1:    # 1. Tcp connect
                    self.handle_tcp(sock, remote)
        except socket.error:
            print 'socket error'
def main():
    server = ThreadingTCPServer(('', 1080), Socks5Server)
    server.serve_forever()
if __name__ == '__main__':
    main()

已经修正Google SyntaxHighlighter无法正确显示Python代码的问题。问题出自shBrushPython.js中定义regexList数组的时候末尾多了一个”,”。删去就行了。神奇的是,只有IEcore才报错……

用Python写socks5服务器端》上有49条评论

  1. Pingback引用通告: Python写简单的网络服务器示例 « Xiaoxia[PG]

    1. Xiaoxia 文章作者

      socks5的用户认证???
      没有做,因为RFC上没有说明具体实现方式。。。
      HTTP代理可能比较容易实现。
      一般socks都不用认证,你想自己使用,可以做IP限制。

      回复
      1. Xiaoxia 文章作者

        你好,read函数是会阻塞的。
        为了避免线程永久阻塞,建议你在这一句的前面给socket设置一个超时树形,代码

        sock.settimeout(5)

        回复
          1. Tydus

            刚才抓了一下包(表示还没有习惯读RFC……),发现Fx和tsocks的请求格式不一样

            Fx是先登录,然后说我要访问什么,而tsocks是直接把所有请求都发过来了,后者的话上面哪个程序的处理方式就有问题了……(Wireshark里写的malformed)

            我试着改一下

            回复
              1. 元谷

                我怎么没看到你发送客户端向目标机的data呢?是不是完成Command包时,也就是返回00成功时,直接发送data给socket服务器,socket服务器再向目标机发送代码!

                回复
                1. Xiaoxia 文章作者

                  额,大概理解你的意思。也是这么工作的。代码比较简介,但TCP代理的功能是完整的。

                  回复
  2. Tianyuan

    hi,我是新人,目前对python非常感兴趣,希望xiaoxia不吝赐教
    最近有一个问题,想请教下xiaoxia

    对于python的网络部分,我知道一个用Django 和 Python 开发 Web 站点
    但我现在想做的一个项目是cs架构,不是bs架构。。。也就是说web service
    客户端直接和服务器链接
    如果是这样,那么用django是不是就不可以做了

    那是用什么别的架构,那天我听人说道Twisted,稍微看了一点,感觉这个比较适合

    ,请问,还有什么别的推荐的架构或者方法么?
    如果我要学习这方面的知识,应该从哪里系统地下手?

    回复
    1. Xiaoxia 文章作者

      django可以呀。你都试试嘛!看你服务器和客户端是怎么通信的,你可以用json或者pickle或者xml或者自定义的协议。据我所知,python有内建的xmlrpc的库。

      回复
  3. kvs

    在VPS上部署了一下,配置SwichySharp翻墙,就不用另外开一个shell,甚爽!!!
    可是,没happy几分钟,,,报异常了,,,
    Connection reset by peer
    纠结,,,

    回复
    1. Xiaoxia 文章作者

      这个异常直接忽略它不就行了吗?我觉得不影响你正常使用吧!!!这个只是说对方关闭了连接而已。

      回复
  4. someone

    这个应该怎么修改,做到只允许本地来访问呢。。。我想配合着stunnel用,这样就不会reset了

    回复
    1. Xiaoxia 文章作者

      只允许本地IP访问吗?绑定到127.0.0.1的IP上就可以了。
      或者也可以用防火墙来设置的。

      回复
  5. inter

    你好,我下载了你的代码,然后放上我的VPS上运行,然后在QQ网络设置那选择SOCKS5代理,地址是我的VPS地址,端口是1080,点击测试,在服务器端缺出现如下错误,请问是什么问题呢?

    socks connection from (‘114.128.205.188′, 57973)
    —————————————-
    Exception happened during processing of request from (‘114.128.205.188′, 57973)
    Traceback (most recent call last):
    File “/usr/lib/python2.7/SocketServer.py”, line 582, in process_request_thread
    self.finish_request(request, client_address)
    File “/usr/lib/python2.7/SocketServer.py”, line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
    File “/usr/lib/python2.7/SocketServer.py”, line 638, in __init__
    self.handle()
    File “./socks5.py”, line 37, in handle
    local = remote.getsockname()
    UnboundLocalError: local variable ‘remote’ referenced before assignment
    —————————————-

    回复
      1. inter

        这个不懂怎么设置了,网络设置那里只有”HTTP代理“、”SOCKS5代理“、”使用浏览器“,貌似没有使用TCP的设置的:(

        回复
  6. Pingback引用通告: 翻墙 | 用Python写的socks5代理及其分支 - 中国数字时代

  7. Pingback引用通告: 用Python写的socks5代理及其分支 « 细节的力量

  8. Pingback引用通告: 翻墙 | 用Python写的socks5代理及其分支 - 中国数字时代

  9. Pingback引用通告: Definite Digest » 用Python写的socks5代理及其分支

    1. Xiaoxia 文章作者

      可能当时看了RFC文档,知道第一个收到的包,最大可能是262吧,但实践起来,通常收到的都不到10个字节!所以这个数字也没有太大的意义,只是表示开辟的缓冲区有那么大。

      回复
  10. 小笨蛋呀

    不错啊,赞一个,我找了N久都没找到像样的代码,就你这个能用,而且还这么简洁,最重要的是还附上了RFC链接,学习到了。xiaxia大神,我太爱你了,不过我是男的,哈哈

    回复
    1. Xiaoxia 文章作者

      谢谢,我写的这个目前只能支持tcp代理,对于大多数人来说,已经能够满足需求。

      回复
  11. Pingback引用通告: 用Python写的socks5代理及其分支 | NOVA.TOO

  12. YC

    师兄我又来了。最近在研究shadowsocks的源码,现在再看过一次你的代码,发现真的很像。。。不过clowwindy大大在你的基础上加了非常巧妙的加密解密函数。整个项目现在很活跃啊~

    回复
  13. Pingback引用通告: 分享一段socket5Server的代码

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>