├── .gitignore ├── .travis.yml ├── Dockerfile ├── README.md ├── build.sh ├── main.go └── proxy.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.8 5 | 6 | script: 7 | - go install 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang 2 | 3 | MAINTAINER ejunjsh 4 | 5 | WORKDIR /root 6 | 7 | RUN go get github.com/ejunjsh/goproxy 8 | 9 | ENTRYPOINT [ "goproxy"] 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # goproxy 2 | [![Build Status](https://travis-ci.org/ejunjsh/goproxy.svg?branch=master)](https://travis-ci.org/ejunjsh/goproxy) 3 | 4 | [![baby-gopher](https://raw.githubusercontent.com/drnic/babygopher-site/gh-pages/images/babygopher-badge.png)](http://www.babygopher.org) 5 | 6 | supports http,socks4/5 at the same time. 7 | 8 | ## install 9 | 10 | go get github.com/ejunjsh/goproxy 11 | 12 | 13 | ## usage 14 | 15 | usage: goproxy 16 | 17 | ## example 18 | 19 | if you run below command in your local or remote machine 20 | 21 | goproxy :8090 22 | 23 | then you can set your proxy address `:8090` on your browser or others that support socks4/5 or http proxy. 24 | 25 | [![](http://idiotsky.top/images3/goproxy.png)](http://idiotsky.top/images3/goproxy.png) 26 | 27 | ## docker 28 | 29 | sudo docker run --net host sjj050121014/goproxy:1.0 30 | 31 | 32 | 😄 enjoy 33 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | sudo docker build -t sjj050121014/goproxy:1.0 . 5 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | ) 9 | 10 | func main() { 11 | 12 | if len(os.Args) == 1 { 13 | fmt.Println("usage: goproxy ") 14 | return 15 | } 16 | 17 | go func() { 18 | c := make(chan os.Signal) 19 | signal.Notify(c, syscall.SIGHUP) 20 | <-c 21 | }() 22 | 23 | Run(os.Args[1]) 24 | } 25 | -------------------------------------------------------------------------------- /proxy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "log" 6 | "io" 7 | "strconv" 8 | "strings" 9 | "net/url" 10 | "fmt" 11 | ) 12 | 13 | 14 | func httpLogf(format string,v ...interface{}){ 15 | log.Printf("[http] "+format,v...) 16 | } 17 | 18 | func socks4Logf(format string,v ...interface{}){ 19 | log.Printf("[socks4] "+format,v...) 20 | } 21 | 22 | func socks5Logf(format string,v ...interface{}){ 23 | log.Printf("[socks5] "+format,v...) 24 | } 25 | 26 | func Run(addr string){ 27 | l,err:= net.Listen("tcp",addr) 28 | if err!=nil{ 29 | log.Println(err) 30 | return 31 | } 32 | log.Println("server listens on ",addr) 33 | for{ 34 | client,err:=l.Accept() 35 | if err !=nil { 36 | log.Println(err) 37 | continue 38 | } 39 | go serve(client) 40 | } 41 | 42 | } 43 | 44 | func serve(client net.Conn){ 45 | var b [1024]byte 46 | n, err := client.Read(b[:]) 47 | if err != nil { 48 | log.Println(err) 49 | return 50 | } 51 | if b[0] == 0x05 { //only for socks5 52 | //response to client: no need to validation 53 | client.Write([]byte{0x05, 0x00}) 54 | n, err = client.Read(b[:]) 55 | var host, port string 56 | switch b[3] { 57 | case 0x01: //IP V4 58 | host = net.IPv4(b[4], b[5], b[6], b[7]).String() 59 | case 0x03: //domain name 60 | host = string(b[5: n-2]) //b[4] length of domain name 61 | case 0x04: //IP V6 62 | host = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String() 63 | } 64 | port = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1])) 65 | server, err := net.Dial("tcp", net.JoinHostPort(host, port)) 66 | if err != nil { 67 | socks5Logf(err.Error()) 68 | return 69 | } 70 | socks5Logf("connect to %s\n",net.JoinHostPort(host, port)) 71 | client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //response to client connection is done. 72 | tunnel(client,server) 73 | } else if b[0] == 0x04 { //only for socks4 74 | var host, port string 75 | host = net.IPv4(b[4], b[5], b[6], b[7]).String() 76 | port = strconv.Itoa(int(b[2])<<8 | int(b[3])) 77 | server, err := net.Dial("tcp", net.JoinHostPort(host, port)) 78 | if err != nil { 79 | socks4Logf(err.Error()) 80 | return 81 | } 82 | socks4Logf("connect to %s\n",net.JoinHostPort(host, port)) 83 | client.Write([]byte{0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //response to client connection is done. 84 | tunnel(client,server) 85 | } else { //http 86 | s:=string(b[:]) 87 | ss:=strings.Split(s," ") 88 | method:=ss[0] 89 | if method=="CONNECT"{ 90 | host:=ss[1] 91 | server, err := net.Dial("tcp", host) 92 | if err != nil { 93 | httpLogf(err.Error()) 94 | return 95 | } 96 | httpLogf("connect to %s\n",host) 97 | success:=[]byte("HTTP/1.1 200 Connection established\r\n\r\n") 98 | _,err=client.Write(success) 99 | if err != nil { 100 | httpLogf(err.Error()) 101 | return 102 | } 103 | tunnel(client,server) 104 | } else { 105 | u:=ss[1] 106 | _url,_:=url.Parse(u) 107 | address:="" 108 | 109 | if strings.Index(_url.Host, ":") == -1 { 110 | if _url.Scheme=="http" { 111 | address = _url.Host + ":80" 112 | }else { 113 | address = _url.Host + ":443" 114 | } 115 | } else { 116 | address = _url.Host 117 | } 118 | 119 | server, err := net.Dial("tcp", address) 120 | if err != nil { 121 | httpLogf(err.Error()) 122 | return 123 | } 124 | httpLogf("forward to %s\n",address) 125 | 126 | fmt.Fprint(server,s) 127 | 128 | tunnel(client,server) 129 | } 130 | } 131 | } 132 | 133 | func tunnel(client net.Conn,server net.Conn){ 134 | go func() { 135 | io.Copy(client, server) 136 | server.Close() 137 | client.Close() 138 | }() 139 | io.Copy(server, client) 140 | client.Close() 141 | server.Close() 142 | } --------------------------------------------------------------------------------