├── README.md ├── .gitignore ├── LICENSE └── valuga.go /README.md: -------------------------------------------------------------------------------- 1 | # valuga 2 | A tool convert SOCKS5 proxy into HTTP proxy 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 mo2zie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /valuga.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "net/http" 7 | "time" 8 | 9 | "golang.org/x/net/proxy" 10 | ) 11 | 12 | func handleHTTP(w http.ResponseWriter, req *http.Request, dialer proxy.Dialer) { 13 | tp := http.Transport{ 14 | Dial: dialer.Dial, 15 | } 16 | resp, err := tp.RoundTrip(req) 17 | if err != nil { 18 | http.Error(w, err.Error(), http.StatusServiceUnavailable) 19 | return 20 | } 21 | defer resp.Body.Close() 22 | copyHeader(w.Header(), resp.Header) 23 | w.WriteHeader(resp.StatusCode) 24 | io.Copy(w, resp.Body) 25 | } 26 | 27 | func copyHeader(dst, src http.Header) { 28 | for k, vv := range src { 29 | for _, v := range vv { 30 | dst.Add(k, v) 31 | } 32 | } 33 | } 34 | 35 | func handleTunnel(w http.ResponseWriter, req *http.Request, dialer proxy.Dialer) { 36 | hijacker, ok := w.(http.Hijacker) 37 | if !ok { 38 | http.Error(w, "Hijacking not supported", http.StatusInternalServerError) 39 | return 40 | } 41 | srcConn, _, err := hijacker.Hijack() 42 | if err != nil { 43 | http.Error(w, err.Error(), http.StatusServiceUnavailable) 44 | return 45 | } 46 | dstConn, err := dialer.Dial("tcp", req.Host) 47 | if err != nil { 48 | srcConn.Close() 49 | return 50 | } 51 | 52 | srcConn.Write([]byte("HTTP/1.1 200 Connection Established\r\n\r\n")) 53 | 54 | go transfer(dstConn, srcConn) 55 | go transfer(srcConn, dstConn) 56 | } 57 | 58 | func transfer(dst io.WriteCloser, src io.ReadCloser) { 59 | defer dst.Close() 60 | defer src.Close() 61 | 62 | io.Copy(dst, src) 63 | } 64 | 65 | func serveHTTP(w http.ResponseWriter, req *http.Request) { 66 | d := &net.Dialer{ 67 | Timeout: 10 * time.Second, 68 | } 69 | dialer, _ := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, d) 70 | 71 | if req.Method == "CONNECT" { 72 | handleTunnel(w, req, dialer) 73 | } else { 74 | handleHTTP(w, req, dialer) 75 | } 76 | } 77 | 78 | func main() { 79 | http.ListenAndServe("127.0.0.1:8124", http.HandlerFunc(serveHTTP)) 80 | } 81 | --------------------------------------------------------------------------------