├── .gitignore ├── README.md ├── gocode └── src │ ├── 1.go │ └── socks.go ├── install.py ├── ip-up.tpl ├── proxy.py ├── requirements.txt ├── socks-gevent.py ├── socks-thread.py └── socks2http.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea 3 | pyenv 4 | ssl 5 | ip-up 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sharp-proxy 2 | =========== 3 | 4 | 一个 代理程序,解决网络复杂的问题(你懂的) 5 | 6 | 假如你的电脑有2个网络出口 7 | 你想让你的程序可以自由选择出口,那么这个正适合你 8 | 例如:adsl+vpm(n) 9 | 或者 adsl+3G 网络 10 | 11 | ---- 12 | 实现方法 13 | 14 | 为每个ip出口启动一个代理服务 15 | 16 | 你的程序要从某个出口出,那么让你的app 从 某个代理出去 即可 17 | 18 | 19 | ----- 20 | 安装方法: 21 | 首先你要安装 py2.7 22 | 23 | socks-thread.py 基于线程的版本 (不在维护了) 24 | socks-gevent.py 基于gevent的版本 pip install gevent 25 | 26 | 27 | 28 | 使用方法: 29 | ---- 30 | 31 | python sharp-proxy/socks-gevent.py --help 32 | $ python socks-gevent.py --help 33 | Usage: 34 | 一个解决复杂网络的 代理服务 35 | 获取vpm 的 本地ip 36 | ifconfig | grep ppp -A 4 37 | ppp0: flags=8051 mtu 1444 38 | inet 10.3.10.55 --> 10.3.10.1 netmask 0xffffff00 39 | 40 | python socks-gevent.py -i ppp0 -p 1080 #绑定vpn 或者adsl的地址 41 | python socks-gevent.py -i ppp1 -p 1080 42 | 43 | 使用指定ip的方式 44 | python socks-gevent.py -i 10.3.10.55 -p 1080 45 | 配合浏览器插件 : switchy 46 | 47 | 配置好脚本 48 | python install.py 49 | ip-up 50 | 软连接 到 51 | sudo ln -s /Users/sdm/share/code/sharp-proxy/ip-up /etc/ppp/ip-up 52 | 53 | 54 | 55 | Options: 56 | -h, --help show this help message and exit 57 | -i IP, --ip=IP 要的绑定ip出口的地址, ppp0 unix/linux/mac 58 | ipconfig ,windows ipconfig 获取 59 | -p PORT, --port=PORT 绑定的socks5代理的本地端口推荐使用 1080 60 | #配置 ppp自动启动代理脚本 61 | sudo python install.py 62 | ln -s /Users/sdm/share/code/sharp-proxy/ip-up=>/etc/ppp/ip-up 63 | 64 | ---- 65 | 66 | todo:socks5 代理转 http 代理 67 | ============== 68 | 69 | python sharp-proxy/socks2http.py -src 1080 -to 1082 -------------------------------------------------------------------------------- /gocode/src/1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func main() { 9 | 10 | var localaddr net.TCPAddr 11 | var remoteaddr net.TCPAddr 12 | localaddr.IP = net.ParseIP("192.168.0.109") 13 | localaddr.Port = 0 14 | remoteaddr.IP = net.ParseIP("192.168.0.1") 15 | remoteaddr.Port = 80 16 | 17 | if localaddr.IP == nil || remoteaddr.IP == nil { 18 | fmt.Println("error") 19 | } 20 | 21 | if _, err := net.DialTCP("tcp", &localaddr, &remoteaddr); err != nil { 22 | fmt.Println(err) 23 | } 24 | 25 | fmt.Println("End") 26 | 27 | } 28 | -------------------------------------------------------------------------------- /gocode/src/socks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "bytes" 5 | // "encoding/binary" 6 | "fmt" 7 | "io" 8 | "log" 9 | "net" 10 | ) 11 | 12 | func recv(buf []byte, m int, conn net.Conn) (n int, err error) { 13 | for nn := 0; n < m; { 14 | nn, err = conn.Read(buf[n:m]) 15 | if nil != err && io.EOF != err { 16 | log.Println("err:", err) 17 | panic(err) 18 | return 19 | } 20 | n += nn 21 | } 22 | return 23 | } 24 | 25 | type reqHello struct { 26 | ver uint8 27 | nmethods uint8 28 | methods [255]uint8 29 | } 30 | 31 | func (msg *reqHello) read(conn net.Conn) (err error) { 32 | _, err = recv(msg.methods[:2], 2, conn) 33 | if nil != err { 34 | return 35 | } 36 | msg.ver, msg.nmethods = msg.methods[0], msg.methods[1] 37 | _, err = recv(msg.methods[:], int(msg.nmethods), conn) 38 | if nil != err { 39 | return 40 | } 41 | return 42 | } 43 | func (msg *reqHello) print() { 44 | log.Println("************") 45 | log.Println("get reqHello msg:") 46 | log.Println("ver:", msg.ver, " nmethods:", msg.nmethods, " methods:", msg.methods[:msg.nmethods]) 47 | log.Println("************") 48 | } 49 | 50 | type ansEcho struct { 51 | ver uint8 52 | method uint8 53 | buf [2]uint8 54 | } 55 | 56 | func (msg *ansEcho) gen(t uint8) { 57 | msg.ver, msg.method = 5, t 58 | msg.buf[0], msg.buf[1] = 5, t 59 | } 60 | func (msg *ansEcho) write(conn net.Conn) { 61 | conn.Write(msg.buf[:]) 62 | } 63 | func (msg *ansEcho) print() { 64 | log.Println("------------------") 65 | log.Println("send ansEcho msg:") 66 | log.Println("ver:", msg.ver, " method:", msg.method) 67 | log.Println("------------------") 68 | } 69 | 70 | type reqMsg struct { 71 | ver uint8 // socks v5: 0x05 72 | cmd uint8 // CONNECT: 0x01, BIND:0x02, UDP ASSOCIATE: 0x03 73 | rsv uint8 //RESERVED 74 | atyp uint8 //IP V4 addr: 0x01, DOMANNAME: 0x03, IP V6 addr: 0x04 75 | dst_addr [255]byte // 76 | dst_port [2]uint8 // 77 | dst_port2 uint16 // 78 | 79 | reqtype string 80 | url string 81 | } 82 | 83 | func (msg *reqMsg) read(conn net.Conn) (err error) { 84 | buf := make([]byte, 4) 85 | _, err = recv(buf, 4, conn) 86 | if nil != err { 87 | return 88 | } 89 | 90 | msg.ver, msg.cmd, msg.rsv, msg.atyp = buf[0], buf[1], buf[2], buf[3] 91 | 92 | if 5 != msg.ver || 0 != msg.rsv { 93 | log.Println("Request Message VER or RSV error!") 94 | return 95 | } 96 | switch msg.atyp { 97 | case 1: //ip v4 98 | _, err = recv(msg.dst_addr[:], 4, conn) 99 | case 4: 100 | _, err = recv(msg.dst_addr[:], 16, conn) 101 | case 3: 102 | _, err = recv(msg.dst_addr[:1], 1, conn) 103 | _, err = recv(msg.dst_addr[1:], int(msg.dst_addr[0]), conn) 104 | } 105 | if nil != err { 106 | return 107 | } 108 | _, err = recv(msg.dst_port[:], 2, conn) 109 | if nil != err { 110 | return 111 | } 112 | //bbuf := bytes.NewBuffer(msg.dst_port[:]) 113 | //err = binary.Read(bbuf, binary.BigEndian, msg.dst_port2) 114 | //if nil != err { 115 | // log.Println(err) 116 | // return 117 | //} 118 | msg.dst_port2 = (uint16(msg.dst_port[0]) << 8) + uint16(msg.dst_port[1]) 119 | 120 | switch msg.cmd { 121 | case 1: 122 | msg.reqtype = "tcp" 123 | case 2: 124 | log.Println("BIND") 125 | case 3: 126 | msg.reqtype = "udp" 127 | } 128 | switch msg.atyp { 129 | case 1: // ipv4 130 | msg.url = fmt.Sprintf("%d.%d.%d.%d:%d", msg.dst_addr[0], msg.dst_addr[1], msg.dst_addr[2], msg.dst_addr[3], msg.dst_port2) 131 | case 3: //DOMANNAME 132 | msg.url = string(msg.dst_addr[1 : 1+msg.dst_addr[0]]) 133 | msg.url += fmt.Sprintf(":%d", msg.dst_port2) 134 | case 4: //ipv6 135 | log.Println("IPV6") 136 | } 137 | return 138 | } 139 | func (msg *reqMsg) print() { 140 | log.Println("---***-----****----***---") 141 | log.Println("get reqMsg:") 142 | log.Println("ver:", msg.ver, " cmd:", msg.cmd, " rsv:", msg.rsv, " atyp", msg.atyp, " dst_addr:", msg.url) 143 | log.Println("---***-----****----***---") 144 | } 145 | 146 | type ansMsg struct { 147 | ver uint8 148 | rep uint8 149 | rsv uint8 150 | atyp uint8 151 | //bnd_addr [255]uint8 152 | //bnd_port [2]uint8 153 | buf [300]uint8 154 | mlen uint16 155 | } 156 | 157 | func (msg *ansMsg) gen(req *reqMsg, rep uint8) { 158 | msg.ver = 5 159 | msg.rep = rep //rfc1928 160 | msg.rsv = 0 161 | msg.atyp = 1 //req.atyp 162 | 163 | msg.buf[0], msg.buf[1], msg.buf[2], msg.buf[3] = msg.ver, msg.rep, msg.rsv, msg.atyp 164 | for i := 5; i < 11; i++ { 165 | msg.buf[i] = 0 166 | } 167 | msg.mlen = 10 168 | //i := 4 169 | //for ; i+4 <= int(req.dst_addr[0]); i++ { 170 | // msg.buf[i] = req.dst_addr[i-4] 171 | //} 172 | //msg.buf[i], msg.buf[i+1] = req.dst_port[0], req.dst_port[1] 173 | //msg.mlen = uint16(i + 2) 174 | } 175 | func (msg *ansMsg) write(conn net.Conn) { 176 | conn.Write(msg.buf[:msg.mlen]) 177 | } 178 | func (msg *ansMsg) print() { 179 | log.Println("***-----****----***---***") 180 | log.Println("send ans Msg:") 181 | log.Println(msg.buf[:msg.mlen]) 182 | log.Println("***-----****----***---***") 183 | } 184 | 185 | func handleConn(conn net.Conn) { 186 | //defer conn.Close() 187 | log.Println("remote addr:", conn.RemoteAddr()) 188 | 189 | var reqhello reqHello 190 | var ansecho ansEcho 191 | var reqmsg reqMsg 192 | var ansmsg ansMsg 193 | 194 | //recv hello 195 | var err error = nil 196 | err = reqhello.read(conn) 197 | if nil != err { 198 | return 199 | } 200 | reqhello.print() 201 | 202 | //send echo 203 | ansecho.gen(0) 204 | ansecho.write(conn) 205 | ansecho.print() 206 | 207 | //recv request 208 | err = reqmsg.read(conn) 209 | if nil != err { 210 | return 211 | } 212 | reqmsg.print() 213 | //connect 214 | var pconn net.Conn 215 | pconn, err = net.Dial(reqmsg.reqtype, reqmsg.url) 216 | println("pconn,", pconn, "err:", err) 217 | println("reqtype:", reqmsg.reqtype, "url:", reqmsg.url) 218 | //defer pconn.Close() 219 | 220 | //reply 221 | //error occur 222 | if nil != err { 223 | ansmsg.gen(&reqmsg, 4) 224 | ansmsg.write(conn) 225 | ansmsg.print() 226 | return 227 | } 228 | //success 229 | ansmsg.gen(&reqmsg, 0) 230 | ansmsg.write(conn) 231 | ansmsg.print() 232 | pipe(conn, pconn) 233 | } 234 | 235 | func resend(in net.Conn, out net.Conn) { 236 | buf := make([]byte, 10240) 237 | for { 238 | n, err := in.Read(buf) 239 | if io.EOF == err { 240 | log.Printf("io.EOF") 241 | return 242 | } else if nil != err { 243 | log.Printf("resend err\n", err) 244 | return 245 | } 246 | out.Write(buf[:n]) 247 | } 248 | } 249 | 250 | func pipe(a net.Conn, b net.Conn) { 251 | go resend(a, b) 252 | go resend(b, a) 253 | } 254 | 255 | func socks5proxy() { 256 | ln, err := net.Listen("tcp", ":1081") 257 | if nil != err { 258 | fmt.Println("Bind Error!") 259 | return 260 | } 261 | 262 | for { 263 | conn, err := ln.Accept() 264 | if nil != err { 265 | fmt.Println("Accept Error!") 266 | continue 267 | } 268 | 269 | go handleConn(conn) 270 | } 271 | } 272 | 273 | func main() { 274 | log.Println() 275 | log.Println("----------------------starting---------------") 276 | socks5proxy() 277 | 278 | } 279 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | __author__ = 'sdm' 3 | 4 | import os 5 | basepath=os.path.dirname(os.path.realpath(__file__)) 6 | ip_up=basepath+'/ip-up' 7 | text = open(basepath+'/ip-up.tpl').read() 8 | code= text.replace('$BASE_PATH',basepath) 9 | fp=open(ip_up,'w') 10 | fp.write(code) 11 | fp.close() 12 | 13 | os.chmod(ip_up,0755) 14 | print "ln -s %s=>/etc/ppp/ip-up" % (ip_up) 15 | os.link(ip_up,'/etc/ppp/ip-up') 16 | -------------------------------------------------------------------------------- /ip-up.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Script which handles the routing issues as necessary for pppd, 4 | # including for PPTP tunnels. Save this script as /etc/ppp/ip-up 5 | # and make sure it is executable. 6 | # 7 | # When the ppp link comes up, this script is called with the following 8 | # parameters 9 | ifname=$1 # the interface name used by pppd (e.g. ppp3) 10 | ttyname=$2 # the tty device name 11 | speed=$3 # the tty device speed 12 | localip=$4 # the local IP address for the interface 13 | remoteip=$5 # the remote IP address 14 | ipparam=$6 # the current IP address before connecting to the VPN 15 | 16 | #参数 17 | #echo $0 $1 $2 $3 $4 $5 $6 >/tmp/ip-up.log 18 | 19 | #关闭之前的进程 20 | ps aux | grep python | grep $ifname | awk '{print "kill " $2 }' | sh 21 | 22 | #启动虚拟环境 23 | source $BASE_PATH/pyenv/bin/activate 24 | /usr/bin/env python $BASE_PATH/socks-gevent.py -i $ifname & 25 | exit 0; -------------------------------------------------------------------------------- /proxy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Simple asynchronous HTTP proxy with tunnelling (CONNECT). 4 | # 5 | # GET/POST proxying based on 6 | # http://groups.google.com/group/python-tornado/msg/7bea08e7a049cf26 7 | # 8 | # Copyright (C) 2012 Senko Rasic 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | # THE SOFTWARE. 27 | 28 | import sys 29 | import socket 30 | 31 | import tornado.httpserver 32 | import tornado.ioloop 33 | import tornado.iostream 34 | import tornado.web 35 | import tornado.httpclient 36 | 37 | __all__ = ['ProxyHandler', 'run_proxy'] 38 | 39 | 40 | class ProxyHandler(tornado.web.RequestHandler): 41 | SUPPORTED_METHODS = ['GET', 'POST', 'CONNECT'] 42 | 43 | @tornado.web.asynchronous 44 | def get(self): 45 | 46 | def handle_response(response): 47 | if response.error and not isinstance(response.error, 48 | tornado.httpclient.HTTPError): 49 | self.set_status(500) 50 | self.write('Internal server error:\n' + str(response.error)) 51 | else: 52 | self.set_status(response.code) 53 | for header in ('Date', 'Cache-Control', 'Server', 54 | 'Content-Type', 'Location'): 55 | v = response.headers.get(header) 56 | if v: 57 | self.set_header(header, v) 58 | if response.body: 59 | self.write(response.body) 60 | self.finish() 61 | 62 | req = tornado.httpclient.HTTPRequest(url=self.request.uri, 63 | method=self.request.method, body=self.request.body, 64 | headers=self.request.headers, follow_redirects=False, 65 | allow_nonstandard_methods=True) 66 | 67 | client = tornado.httpclient.AsyncHTTPClient() 68 | try: 69 | client.fetch(req, handle_response) 70 | except tornado.httpclient.HTTPError as e: 71 | if hasattr(e, 'response') and e.response: 72 | handle_response(e.response) 73 | else: 74 | self.set_status(500) 75 | self.write('Internal server error:\n' + str(e)) 76 | self.finish() 77 | 78 | @tornado.web.asynchronous 79 | def post(self): 80 | return self.get() 81 | 82 | @tornado.web.asynchronous 83 | def connect(self): 84 | host, port = self.request.uri.split(':') 85 | client = self.request.connection.stream 86 | 87 | def read_from_client(data): 88 | upstream.write(data) 89 | 90 | def read_from_upstream(data): 91 | client.write(data) 92 | 93 | def client_close(data=None): 94 | if upstream.closed(): 95 | return 96 | if data: 97 | upstream.write(data) 98 | upstream.close() 99 | 100 | def upstream_close(data=None): 101 | if client.closed(): 102 | return 103 | if data: 104 | client.write(data) 105 | client.close() 106 | 107 | def start_tunnel(): 108 | client.read_until_close(client_close, read_from_client) 109 | upstream.read_until_close(upstream_close, read_from_upstream) 110 | client.write(b'HTTP/1.0 200 Connection established\r\n\r\n') 111 | 112 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) 113 | upstream = tornado.iostream.IOStream(s) 114 | upstream.connect((host, int(port)), start_tunnel) 115 | 116 | 117 | def run_proxy(port, start_ioloop=True): 118 | """ 119 | Run proxy on the specified port. If start_ioloop is True (default), 120 | the tornado IOLoop will be started immediately. 121 | """ 122 | app = tornado.web.Application([ 123 | (r'.*', ProxyHandler), 124 | ]) 125 | app.listen(port) 126 | ioloop = tornado.ioloop.IOLoop.instance() 127 | if start_ioloop: 128 | ioloop.start() 129 | 130 | if __name__ == '__main__': 131 | port = 8888 132 | if len(sys.argv) > 1: 133 | port = int(sys.argv[1]) 134 | 135 | print ("Starting HTTP proxy on port %d" % port) 136 | run_proxy(port) 137 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | gevent==1.0.1 2 | greenlet==0.4.4 3 | netifaces==0.10.4 4 | wsgiref==0.1.2 5 | -------------------------------------------------------------------------------- /socks-gevent.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding:utf-8 3 | 4 | __author__ = 'sdm' 5 | 6 | import socket 7 | import sys 8 | import struct 9 | import os 10 | reload(sys) 11 | sys.setdefaultencoding('utf-8') 12 | from optparse import OptionParser 13 | 14 | import re 15 | import gevent 16 | from gevent import monkey; 17 | 18 | monkey.patch_all() 19 | 20 | from gevent.server import StreamServer 21 | 22 | 23 | def hanlder(sock, address): 24 | ''' 25 | socks5 代理的 26 | ''' 27 | global options 28 | print options 29 | rfile = sock.makefile() 30 | try: 31 | print 'socks connection from ', address 32 | # 1. Version 33 | recv_data = sock.recv(262) 34 | sock.sendall(b"\x05\x00"); 35 | # 2. Request 36 | data = rfile.read(4) 37 | mode = ord(data[1]) 38 | addrtype = ord(data[3]) 39 | if addrtype == 1: # IPv4 40 | addr = socket.inet_ntoa(rfile.read(4)) 41 | elif addrtype == 3: # Domain name 42 | # 域名长度一个字节限制 43 | addr = rfile.read(ord(sock.recv(1)[0])) 44 | port = struct.unpack('>H', rfile.read(2)) 45 | print 'addr type:', addrtype, 'mode:', mode, 'addr:', addr, 'port:', port 46 | reply = b"\x05\x00\x00\x01" 47 | try: 48 | if mode == 1: # 1. Tcp connect 49 | remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 50 | # 选择某个ip出口 51 | # src=('10.3.10.30',0) 52 | # 比如是一个 vpn的本地的ip地址 53 | bind_ip = options.ip 54 | if not bind_ip is None: 55 | remote.bind((bind_ip, 0)) 56 | print 'remote connect:', addr, port[0] 57 | remote.connect((addr, port[0])) 58 | 59 | print 'Tcp connect to', addr, port[0] 60 | else: 61 | reply = b"\x05\x07\x00\x01" # Command not supported 62 | local = remote.getsockname() 63 | reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1]) 64 | except socket.error: 65 | # Connection refused 66 | reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' 67 | sock.send(reply) 68 | # 3. Transfering 69 | if reply[1] == '\x00': # Success 70 | print 'Transfering Success' 71 | if mode == 1: # 1. Tcp connect 72 | print 'tcp connect' 73 | handle_tcp(sock, remote) 74 | 75 | except socket.error: 76 | print 'socket error' 77 | 78 | 79 | def handle_tcp(sock, remote): 80 | fdset = [sock, remote] 81 | while True: 82 | r, w, e = gevent.select.select(fdset, [], []) 83 | if sock in r: 84 | if remote.send(sock.recv(4096)) <= 0: break 85 | if remote in r: 86 | if sock.send(remote.recv(4096)) <= 0: break 87 | 88 | def get_ppp0(): 89 | import netifaces as ni 90 | 91 | 92 | def main(): 93 | global options 94 | usage = ''' 95 | 一个解决复杂网络的 代理服务 96 | 获取vpm 的 本地ip 97 | ifconfig | grep ppp -A 4 98 | ppp0: flags=8051 mtu 1444 99 | inet 10.3.10.55 --> 10.3.10.1 netmask 0xffffff00 100 | 101 | python socks-gevent.py -i ppp0 -p 1080 #绑定vpn 或者adsl的地址 102 | python socks-gevent.py -i ppp1 -p 1080 103 | 104 | 使用指定ip的方式 105 | python socks-gevent.py -i 10.3.10.55 -p 1080 106 | 配合浏览器插件 : switchy 107 | 108 | 配置好脚本 109 | python install.py 110 | ip-up 111 | 软连接 到 112 | sudo ln -s %s/ip-up /etc/ppp/ip-up 113 | 114 | ''' % (os.path.dirname(os.path.realpath(__file__)),) 115 | parser = OptionParser(usage=usage) 116 | 117 | parser.add_option("-i", "--ip", dest="ip", 118 | help="要的绑定ip出口的地址, ppp0 \n unix/linux/mac ipconfig ,windows ipconfig 获取") 119 | parser.add_option("-p", "--port", dest="port", default=1080, type="int", 120 | help="绑定的socks5代理的本地端口推荐使用 1080 ") 121 | 122 | options, arg = parser.parse_args() 123 | print "opt:",options 124 | 125 | if not options.ip is None and options.ip[0:3]=='ppp': 126 | '使用指定接口的方式' 127 | import netifaces as ni 128 | interfaces=ni.interfaces() 129 | if not options.ip in interfaces: 130 | print("error interface error,available interface:\n") 131 | for p in interfaces: 132 | print p 133 | return 134 | a=ni.ifaddresses(options.ip) 135 | print 'a',a 136 | print a 137 | if not a.has_key(2) or not len(a[2]) : 138 | print "接口错误" 139 | return 140 | options.ip=a[2][0]['addr'] 141 | print("new ip",options.ip) 142 | 143 | print('listen port:', options.port, 'local ip:', options.ip) 144 | server = gevent.server.StreamServer(('', options.port), hanlder) 145 | server.serve_forever() 146 | 147 | 148 | if __name__ == '__main__': 149 | main() 150 | -------------------------------------------------------------------------------- /socks-thread.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding:utf-8 3 | 4 | __author__ = 'sdm' 5 | import socket 6 | import sys 7 | import select 8 | import SocketServer 9 | import struct 10 | 11 | reload(sys) 12 | sys.setdefaultencoding('utf-8') 13 | from optparse import OptionParser 14 | 15 | 16 | class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass 17 | 18 | 19 | class Socks5Server(SocketServer.StreamRequestHandler): 20 | def handle_tcp(self, sock, remote): 21 | fdset = [sock, remote] 22 | while True: 23 | r, w, e = select.select(fdset, [], []) 24 | if sock in r: 25 | if remote.send(sock.recv(4096)) <= 0: break 26 | if remote in r: 27 | if sock.send(remote.recv(4096)) <= 0: break 28 | 29 | def handle(self): 30 | global options 31 | try: 32 | print 'socks connection from ', self.client_address 33 | sock = self.connection 34 | # 1. Version 35 | sock.recv(262) 36 | sock.send(b"\x05\x00"); 37 | # 2. Request 38 | data = self.rfile.read(4) 39 | mode = ord(data[1]) 40 | addrtype = ord(data[3]) 41 | if addrtype == 1: # IPv4 42 | addr = socket.inet_ntoa(self.rfile.read(4)) 43 | elif addrtype == 3: # Domain name 44 | addr = self.rfile.read(ord(sock.recv(1)[0])) 45 | port = struct.unpack('>H', self.rfile.read(2)) 46 | reply = b"\x05\x00\x00\x01" 47 | try: 48 | if mode == 1: # 1. Tcp connect 49 | remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 50 | #选择某个ip出口 51 | #src=('10.3.10.30',0) 52 | local_ip = options.ip 53 | if not local_ip is None: 54 | remote.bind((local_ip, 0)) 55 | remote.connect((addr, port[0])) 56 | 57 | print 'Tcp connect to', addr, port[0] 58 | else: 59 | reply = b"\x05\x07\x00\x01" # Command not supported 60 | local = remote.getsockname() 61 | reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1]) 62 | except socket.error: 63 | # Connection refused 64 | reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' 65 | sock.send(reply) 66 | # 3. Transfering 67 | if reply[1] == '\x00': # Success 68 | if mode == 1: # 1. Tcp connect 69 | self.handle_tcp(sock, remote) 70 | except socket.error: 71 | print 'socket error' 72 | 73 | 74 | def main(): 75 | server = ThreadingTCPServer(('', 1080), Socks5Server) 76 | server.serve_forever() 77 | 78 | 79 | def main(): 80 | global options 81 | usage = ''' 82 | 一个解决复杂网络的 代理服务 83 | 获取vpm 的 本地ip 84 | ifconfig | grep ppp -A 4 85 | ppp0: flags=8051 mtu 1444 86 | inet 10.3.10.55 --> 10.3.10.1 netmask 0xffffff00 87 | 88 | python socks-gevent.py -i 10.3.10.55 -p 1080 89 | 配合浏览器插件 : switchy 90 | 91 | ''' 92 | parser = OptionParser(usage=usage) 93 | 94 | parser.add_option("-i", "--ip", dest="ip", 95 | help="要的绑定ip出口的地址, unix/linux/mac ipconfig ,windows ipconfig 获取") 96 | parser.add_option("-p", "--port", dest="port", default=1080, type="int", 97 | help="绑定的socks5代理的本地端口推荐使用 1080 ") 98 | 99 | options, arg = parser.parse_args() 100 | #print help(options) 101 | #print (options['ip']) 102 | print('listen port:', options.port, 'local ip:', options.ip) 103 | 104 | server = ThreadingTCPServer(('', options.port), Socks5Server) 105 | server.serve_forever() 106 | 107 | 108 | if __name__ == '__main__': 109 | main() 110 | -------------------------------------------------------------------------------- /socks2http.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | __author__ = 'sdm' 3 | 4 | import socks 5 | import socket 6 | socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 8080) 7 | socket.socket = socks.socksocket 8 | import urllib2 9 | print urllib2.urlopen('http://www.google.com').read() 10 | 11 | a=urllib2.urlopen('http://localhost/info.php'); 12 | print a.read() --------------------------------------------------------------------------------