├── README.md ├── .gitignore ├── goproxy_http_v0.01.go └── goproxy_socks5_v0.01.go /README.md: -------------------------------------------------------------------------------- 1 | goproxy 2 | ======= 3 | 4 | a proxy server implemented in golang 5 | 6 | - 7 | SOCKS Protocol Version 5 8 | 9 | http://www.ietf.org/rfc/rfc1928.txt 10 | 11 | http://www.ietf.org/rfc/rfc1929.txt 12 | 13 | - 14 | 15 | v0.01 - 2012.10.07 16 | ------- 17 | implement tcp proxy in socks v5 18 | 19 | implement http proxy 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /goproxy_http_v0.01.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "io/ioutil" 6 | "log" 7 | "os" 8 | "io" 9 | ) 10 | 11 | func handler(w http.ResponseWriter, r *http.Request) { 12 | 13 | log.Println("----------------------------------") 14 | log.Println("RequestURI", r.RequestURI ) 15 | log.Println("RemoteAddr", r.RemoteAddr) 16 | //log.Println("URL", r.URL) 17 | log.Println("----------------------------------") 18 | 19 | //http: Request.RequestURI can't be set in client requests. 20 | //http://golang.org/src/pkg/net/http/client.go 21 | r.RequestURI = "" 22 | 23 | //log.Println("RequestURI", r.RequestURI) 24 | resp, err := http.DefaultClient.Do(r) 25 | defer resp.Body.Close() 26 | if err != nil { 27 | panic(err) 28 | } 29 | for k, v := range resp.Header { 30 | for _, vv := range v { 31 | w.Header().Add(k, vv) 32 | } 33 | } 34 | 35 | w.WriteHeader(resp.StatusCode) 36 | result, err := ioutil.ReadAll(resp.Body) 37 | if err != nil && err != io.EOF { 38 | panic(err) 39 | } 40 | w.Write(result) 41 | } 42 | 43 | func main() { 44 | http.HandleFunc("/", handler) 45 | log.Println("Start serving on port 8000") 46 | http.ListenAndServe(":8000", nil) 47 | os.Exit(0) 48 | } 49 | -------------------------------------------------------------------------------- /goproxy_socks5_v0.01.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 | //defer pconn.Close() 217 | 218 | //reply 219 | //error occur 220 | if nil != err { 221 | ansmsg.gen(&reqmsg, 4) 222 | ansmsg.write(conn) 223 | ansmsg.print() 224 | return 225 | } 226 | //success 227 | ansmsg.gen(&reqmsg, 0) 228 | ansmsg.write(conn) 229 | ansmsg.print() 230 | pipe(conn, pconn) 231 | } 232 | 233 | func resend(in net.Conn, out net.Conn) { 234 | buf := make([]byte, 10240) 235 | for { 236 | n, err := in.Read(buf) 237 | if io.EOF == err { 238 | log.Printf("io.EOF") 239 | return 240 | } else if nil != err { 241 | log.Printf("resend err\n", err) 242 | return 243 | } 244 | out.Write(buf[:n]) 245 | } 246 | } 247 | 248 | func pipe(a net.Conn, b net.Conn) { 249 | go resend(a, b) 250 | go resend(b, a) 251 | } 252 | 253 | func socks5proxy() { 254 | ln, err := net.Listen("tcp", ":8000") 255 | if nil != err { 256 | fmt.Println("Bind Error!") 257 | return 258 | } 259 | 260 | for { 261 | conn, err := ln.Accept() 262 | if nil != err { 263 | fmt.Println("Accept Error!") 264 | continue 265 | } 266 | 267 | go handleConn(conn) 268 | } 269 | } 270 | 271 | func main() { 272 | log.Println() 273 | log.Println("----------------------starting---------------") 274 | socks5proxy() 275 | 276 | } 277 | --------------------------------------------------------------------------------