├── .gitignore
├── Makefile
├── README.md
├── main.go
├── media
└── whatsmyip-results.png
├── proxy-ng.pem
├── socks5-proxies.json
├── useragents.json
├── vendor
└── github.com
│ ├── eahydra
│ └── socks
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── cmd
│ │ └── socksd
│ │ │ ├── README.md
│ │ │ ├── cipher.go
│ │ │ ├── cipher_conn.go
│ │ │ ├── config.go
│ │ │ ├── decorate_client.go
│ │ │ ├── decorate_conn.go
│ │ │ ├── decorate_direct.go
│ │ │ ├── decorate_listener.go
│ │ │ ├── dns_cache.go
│ │ │ ├── log.go
│ │ │ ├── main.go
│ │ │ ├── pac_generator.go
│ │ │ ├── pac_updater.go
│ │ │ └── upstream_client.go
│ │ ├── direct.go
│ │ ├── example_test.go
│ │ ├── http_proxy.go
│ │ ├── shadowsocks_client.go
│ │ ├── socks4.go
│ │ ├── socks4_test.go
│ │ ├── socks5_client.go
│ │ ├── socks5_client_test.go
│ │ └── socks5_server.go
│ └── elazarl
│ └── goproxy
│ ├── LICENSE
│ ├── README.md
│ ├── actions.go
│ ├── all.bash
│ ├── ca.pem
│ ├── certs.go
│ ├── chunked.go
│ ├── counterecryptor.go
│ ├── counterecryptor_test.go
│ ├── ctx.go
│ ├── dispatcher.go
│ ├── doc.go
│ ├── examples
│ ├── goproxy-basic
│ │ ├── README.md
│ │ └── main.go
│ ├── goproxy-eavesdropper
│ │ └── main.go
│ ├── goproxy-httpdump
│ │ ├── README.md
│ │ └── httpdump.go
│ ├── goproxy-jquery-version
│ │ ├── README.md
│ │ ├── jquery1.html
│ │ ├── jquery2.html
│ │ ├── jquery_homepage.html
│ │ ├── jquery_test.go
│ │ ├── main.go
│ │ ├── php_man.html
│ │ └── w3schools.html
│ ├── goproxy-no-reddit-at-worktime
│ │ ├── README.md
│ │ └── noreddit.go
│ ├── goproxy-sokeepalive
│ │ └── sokeepalive.go
│ ├── goproxy-sslstrip
│ │ └── sslstrip.go
│ ├── goproxy-stats
│ │ ├── README.md
│ │ └── main.go
│ ├── goproxy-transparent
│ │ ├── README.md
│ │ ├── proxy.sh
│ │ └── transparent.go
│ ├── goproxy-upside-down-ternet
│ │ └── main.go
│ └── goproxy-yui-minify
│ │ └── yui.go
│ ├── ext
│ ├── auth
│ │ ├── basic.go
│ │ └── basic_test.go
│ ├── html
│ │ ├── cp1255.html
│ │ ├── cp1255.txt
│ │ ├── html.go
│ │ └── html_test.go
│ └── image
│ │ └── image.go
│ ├── https.go
│ ├── key.pem
│ ├── proxy.go
│ ├── proxy_test.go
│ ├── regretable
│ ├── regretreader.go
│ └── regretreader_test.go
│ ├── responses.go
│ ├── signer.go
│ ├── signer_test.go
│ ├── test_data
│ ├── baby.jpg
│ ├── football.png
│ └── panda.png
│ └── transport
│ ├── roundtripper.go
│ ├── transport.go
│ └── util.go
└── version.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | proxy-ng
3 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | GIT_VERSION=`git log --pretty=format:"%h" -1`
2 | BIN_VERSION=`cat version.txt`
3 |
4 | osx:
5 | GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X main.gitCommit=${GIT_VERSION} -X main.appVersion=${BIN_VERSION}" -o proxy-ng-darwin main.go
6 |
7 | linux:
8 | GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X main.gitCommit=${GIT_VERSION} -X main.appVersion=${BIN_VERSION}" -o proxy-ng-linux main.go
9 |
10 | windows:
11 | GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X main.gitCommit=${GIT_VERSION} -X main.appVersion=${BIN_VERSION}" -o proxy-ng-windows main.go
12 |
13 | build: osx linux windows
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Proxy-ng
2 |
3 | ## Purpose
4 |
5 | Wanted to make use of multiple socks proxies in a random order. Along with using socks proxies in a random order, I wanted each request to have a random useragent.
6 |
7 | ## Setup
8 |
9 | ### Build
10 |
11 | * `git clone https://github.com/jamesbcook/proxy-ng.git`
12 | * `make`
13 | * `./proxy-ng -help`
14 |
15 | ### Pre-Built binary
16 |
17 | * Download from [here](https://github.com/jamesbcook/proxy-ng/releases)
18 | * `./proxy-ng -help`
19 |
20 | ## Running
21 |
22 | Proxy-ng opens the following ports:
23 |
24 | * 9292 for the local socks proxy
25 | * 9293 for the local http proxy
26 |
27 | Unless specified by a flag, Proxy-ng will use look for the following files in its running directory:
28 |
29 | * useragents.json
30 | * socks5-proxies.json
31 |
32 | ## Example
33 |
34 | I use [cloud-proxy](https://github.com/tomsteele/cloud-proxy) to setup multiple socks proxies
35 |
36 | ```bash
37 | ./cloud-proxy -token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -key 'xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx' -count 5
38 | 2018/07/01 18:12:22 Creating 1 droplets to region nyc1
39 | 2018/07/01 18:12:23 Creating 1 droplets to region sgp1
40 | 2018/07/01 18:12:24 Creating 1 droplets to region lon1
41 | 2018/07/01 18:12:25 Creating 1 droplets to region nyc3
42 | 2018/07/01 18:12:26 Creating 1 droplets to region ams3
43 | 2018/07/01 18:12:27 Droplets deployed. Waiting 100 seconds...
44 | 2018/07/01 18:14:08 SSH proxy started on port 55555 on droplet name: cloud-proxy-OucHZHiV IP: 159.65.236.62
45 | 2018/07/01 18:14:09 SSH proxy started on port 55556 on droplet name: cloud-proxy-q4AZAYVN IP: 178.128.95.250
46 | 2018/07/01 18:14:10 SSH proxy started on port 55557 on droplet name: cloud-proxy-RQLq0UQm IP: 139.59.173.24
47 | 2018/07/01 18:14:11 SSH proxy started on port 55558 on droplet name: cloud-proxy-eVd59B6d IP: 209.97.153.98
48 | 2018/07/01 18:14:11 SSH proxy started on port 55559 on droplet name: cloud-proxy-oSRSfFO1 IP: 188.166.6.62
49 | 2018/07/01 18:14:11 proxychains config
50 | socks5 127.0.0.1 55555
51 | socks5 127.0.0.1 55556
52 | socks5 127.0.0.1 55557
53 | socks5 127.0.0.1 55558
54 | socks5 127.0.0.1 55559
55 | 2018/07/01 18:14:11 socksd config
56 | "upstreams": [
57 | {"type": "socks5", "address": "127.0.0.1:55555"},
58 | {"type": "socks5", "address": "127.0.0.1:55556"},
59 | {"type": "socks5", "address": "127.0.0.1:55557"},
60 | {"type": "socks5", "address": "127.0.0.1:55558"},
61 | {"type": "socks5", "address": "127.0.0.1:55559"}
62 | ]
63 | 2018/07/01 18:14:11 Please CTRL-C to destroy droplets
64 | ```
65 |
66 | After pointing the browser to the local http listener setup by Proxy-ng and heading to whatsmyip.org it showed my hostname and IP to be different.
67 |
68 | 
69 |
70 | ## Help Output
71 |
72 | ```text
73 | Usage of ./proxy-ng:
74 | -http string
75 | HTTP listener to accept connections, this changes the useragent on each request (default "localhost:9293")
76 | -socks string
77 | Local socks listener to accept connections (default "localhost:9292")
78 | -socksFile string
79 | Socks file that contains socks proxies to use (default "socks5-proxies.json")
80 | -uaFile string
81 | Json file that contains useragents to use (default "useragents.json")
82 | -verbose
83 | Verbose output from proxy
84 | -version
85 | Current Version
86 | ```
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "flag"
7 | "fmt"
8 | "log"
9 | "math/rand"
10 | "net"
11 | "net/http"
12 | "os"
13 | "time"
14 |
15 | "github.com/eahydra/socks"
16 | "github.com/elazarl/goproxy"
17 | "github.com/jamesbcook/print"
18 | )
19 |
20 | var (
21 | appVersion string
22 | gitCommit string
23 | )
24 |
25 | //UserAgent contains a slice of useragents to be used
26 | type UserAgent struct {
27 | Names []string `json:"UserAgents"`
28 | }
29 |
30 | //SocksProxy contains a slice of proxies to be used
31 | type SocksProxy struct {
32 | Names []string `json:"Proxies"`
33 | }
34 |
35 | //UpstreamDialer contains a slice of socks dialers to be used
36 | type UpstreamDialer struct {
37 | forwardDialers []socks.Dialer
38 | }
39 |
40 | func init() {
41 | rand.Seed(time.Now().UTC().UnixNano())
42 | }
43 |
44 | type flags struct {
45 | userAgentFile string
46 | socks5File string
47 | socksListener string
48 | httpListener string
49 | verbose bool
50 | }
51 |
52 | func flagSetup() *flags {
53 | uaFile := flag.String("uaFile", "useragents.json", "Json file that contains useragents to use")
54 | socksFile := flag.String("socksFile", "socks5-proxies.json", "Socks file that contains socks proxies to use")
55 | socksListen := flag.String("socks", "localhost:9292", "Local socks listener to accept connections")
56 | httpListen := flag.String("http", "localhost:9293", "HTTP listener to accept connections, this changes the useragent on each request")
57 | verbose := flag.Bool("verbose", false, "Verbose output from proxy")
58 | version := flag.Bool("version", false, "Current Version")
59 | flag.Parse()
60 | if *version {
61 | fmt.Printf("proxy-ng v%s %s\n", appVersion, gitCommit)
62 | os.Exit(0)
63 | }
64 | return &flags{userAgentFile: *uaFile, socks5File: *socksFile,
65 | socksListener: *socksListen, httpListener: *httpListen,
66 | verbose: *verbose}
67 | }
68 |
69 | func main() {
70 | myFlags := flagSetup()
71 | f, err := os.Open(myFlags.userAgentFile)
72 | if err != nil {
73 | print.Badln(err)
74 | }
75 | f2, err := os.Open(myFlags.socks5File)
76 | if err != nil {
77 | print.Badln(err)
78 | }
79 | var buf bytes.Buffer
80 | buf.ReadFrom(f)
81 | ua := &UserAgent{}
82 | if err := json.Unmarshal(buf.Bytes(), ua); err != nil {
83 | print.Badln(err)
84 | }
85 | buf.Reset()
86 | proxies := &SocksProxy{}
87 | buf.ReadFrom(f2)
88 | if err := json.Unmarshal(buf.Bytes(), proxies); err != nil {
89 | print.Badln(err)
90 | }
91 | var router socks.Dialer
92 | proxy := goproxy.NewProxyHttpServer()
93 | if myFlags.verbose {
94 | router = logBuildUpStream(BuildUpstreamRouter)(proxies.Names)
95 | proxy.ConnectDial = func(network, address string) (net.Conn, error) {
96 | return logDialer(router.Dial)(network, address)
97 | }
98 | proxy.Tr.Dial = func(network, address string) (net.Conn, error) {
99 | return logDialer(router.Dial)(network, address)
100 | }
101 | } else {
102 | router = BuildUpstreamRouter(proxies.Names)
103 | proxy.ConnectDial = func(network, address string) (net.Conn, error) {
104 | return router.Dial(network, address)
105 | }
106 | proxy.Tr.Dial = func(network, address string) (net.Conn, error) {
107 | return router.Dial(network, address)
108 | }
109 | }
110 | socksListen, err := net.Listen("tcp", myFlags.socksListener)
111 | if err != nil {
112 | print.Badln(err)
113 | }
114 | if myFlags.verbose {
115 | print.Goodf("Started socks listener on %s\n", myFlags.socksListener)
116 | }
117 | socksvr, err := socks.NewSocks5Server(router)
118 | if err != nil {
119 | print.Badln(err)
120 | }
121 | httpListen, err := net.Listen("tcp", myFlags.httpListener)
122 | if err != nil {
123 | print.Badln(err)
124 | }
125 | if myFlags.verbose {
126 | print.Goodf("Started http listener on %s\n", myFlags.httpListener)
127 | }
128 | proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
129 | proxy.OnRequest().DoFunc(
130 | func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
131 | r.Header.Set("User-Agent", ua.randomName())
132 | return r, nil
133 | })
134 | go func() {
135 | http.Serve(httpListen, proxy)
136 | }()
137 | print.Goodln("Ready")
138 | if err := socksvr.Serve(socksListen); err != nil {
139 | print.Badln(err)
140 | }
141 | }
142 |
143 | func (ua UserAgent) randomName() string {
144 | max := len(ua.Names)
145 | if max == 0 {
146 | return ua.Names[0]
147 | }
148 | randomUA := 0 + rand.Intn(max-0)
149 | return ua.Names[randomUA]
150 | }
151 |
152 | //NewUpstreamDialer to be added to the array of dialers
153 | func NewUpstreamDialer(forwardDialers []socks.Dialer) *UpstreamDialer {
154 | return &UpstreamDialer{
155 | forwardDialers: forwardDialers,
156 | }
157 | }
158 |
159 | func (u *UpstreamDialer) getRandomDialer() socks.Dialer {
160 | max := len(u.forwardDialers)
161 | if max == 0 {
162 | return u.forwardDialers[0]
163 | }
164 | randomDialer := 0 + rand.Intn(max-0)
165 | return u.forwardDialers[randomDialer]
166 | }
167 |
168 | func logDialer(f func(network, address string) (net.Conn, error)) func(network, address string) (net.Conn, error) {
169 | return func(network, address string) (net.Conn, error) {
170 | conn, err := f(network, address)
171 | print.Statusf("Connecting to %v\n", conn.RemoteAddr())
172 | return conn, err
173 | }
174 | }
175 |
176 | //Dial is a custom dialer that picks a random dialer before it makes it's connection
177 | func (u *UpstreamDialer) Dial(network, address string) (net.Conn, error) {
178 | router := u.getRandomDialer()
179 | conn, err := router.Dial(network, address)
180 | if err != nil {
181 | return nil, err
182 | }
183 | return conn, nil
184 | }
185 |
186 | func logBuildUpStream(f func(proxies []string) socks.Dialer) func(proxies []string) socks.Dialer {
187 | return func(proxies []string) socks.Dialer {
188 | for x := range proxies {
189 | print.Statusf("Loading %s\n", proxies[x])
190 | }
191 | defer print.Goodln("Loading complete")
192 | return f(proxies)
193 | }
194 | }
195 |
196 | //BuildUpstreamRouter populates the slice of dialers
197 | func BuildUpstreamRouter(proxies []string) socks.Dialer {
198 | var allForward []socks.Dialer
199 | for _, proxy := range proxies {
200 | forward, err := socks.NewSocks5Client("tcp", proxy, "", "", socks.Direct)
201 | if err != nil {
202 | log.Fatal(err)
203 | }
204 | allForward = append(allForward, forward)
205 | }
206 | return NewUpstreamDialer(allForward)
207 | }
208 |
--------------------------------------------------------------------------------
/media/whatsmyip-results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesbcook/proxy-ng/ee3e213ab8d9498a6b7743f0acf5ff30a44ffb38/media/whatsmyip-results.png
--------------------------------------------------------------------------------
/proxy-ng.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIF9DCCA9ygAwIBAgIJAODqYUwoVjJkMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYD
3 | VQQGEwJJTDEPMA0GA1UECAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoM
4 | B0dvUHJveHkxEDAOBgNVBAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0
5 | aHViLmlvMSAwHgYJKoZIhvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTAeFw0xNzA0
6 | MDUyMDAwMTBaFw0zNzAzMzEyMDAwMTBaMIGOMQswCQYDVQQGEwJJTDEPMA0GA1UE
7 | CAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoMB0dvUHJveHkxEDAOBgNV
8 | BAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0aHViLmlvMSAwHgYJKoZI
9 | hvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
10 | ADCCAgoCggIBAJ4Qy+H6hhoY1s0QRcvIhxrjSHaO/RbaFj3rwqcnpOgFq07gRdI9
11 | 3c0TFKQJHpgv6feLRhEvX/YllFYu4J35lM9ZcYY4qlKFuStcX8Jm8fqpgtmAMBzP
12 | sqtqDi8M9RQGKENzU9IFOnCV7SAeh45scMuI3wz8wrjBcH7zquHkvqUSYZz035t9
13 | V6WTrHyTEvT4w+lFOVN2bA/6DAIxrjBiF6DhoJqnha0SZtDfv77XpwGG3EhA/qoh
14 | hiYrDruYK7zJdESQL44LwzMPupVigqalfv+YHfQjbhT951IVurW2NJgRyBE62dLr
15 | lHYdtT9tCTCrd+KJNMJ+jp9hAjdIu1Br/kifU4F4+4ZLMR9Ueji0GkkPKsYdyMnq
16 | j0p0PogyvP1l4qmboPImMYtaoFuYmMYlebgC9LN10bL91K4+jLt0I1YntEzrqgJo
17 | WsJztYDw543NzSy5W+/cq4XRYgtq1b0RWwuUiswezmMoeyHZ8BQJe2xMjAOllASD
18 | fqa8OK3WABHJpy4zUrnUBiMuPITzD/FuDx4C5IwwlC68gHAZblNqpBZCX0nFCtKj
19 | YOcI2So5HbQ2OC8QF+zGVuduHUSok4hSy2BBfZ1pfvziqBeetWJwFvapGB44nIHh
20 | WKNKvqOxLNIy7e+TGRiWOomrAWM18VSR9LZbBxpJK7PLSzWqYJYTRCZHAgMBAAGj
21 | UzBRMB0GA1UdDgQWBBR4uDD9Y6x7iUoHO+32ioOcw1ICZTAfBgNVHSMEGDAWgBR4
22 | uDD9Y6x7iUoHO+32ioOcw1ICZTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
23 | CwUAA4ICAQAaCEupzGGqcdh+L7BzhX7zyd7yzAKUoLxFrxaZY34Xyj3lcx1XoK6F
24 | AqsH2JM25GixgadzhNt92JP7vzoWeHZtLfstrPS638Y1zZi6toy4E49viYjFk5J0
25 | C6ZcFC04VYWWx6z0HwJuAS08tZ37JuFXpJGfXJOjZCQyxse0Lg0tuKLMeXDCk2Y3
26 | Ba0noeuNyHRoWXXPyiUoeApkVCU5gIsyiJSWOjhJ5hpJG06rQNfNYexgKrrraEin
27 | o0jmEMtJMx5TtD83hSnLCnFGBBq5lkE7jgXME1KsbIE3lJZzRX1mQwUK8CJDYxye
28 | i6M/dzSvy0SsPvz8fTAlprXRtWWtJQmxgWENp3Dv+0Pmux/l+ilk7KA4sMXGhsfr
29 | bvTOeWl1/uoFTPYiWR/ww7QEPLq23yDFY04Q7Un0qjIk8ExvaY8lCkXMgc8i7sGY
30 | VfvOYb0zm67EfAQl3TW8Ky5fl5CcxpVCD360Bzi6hwjYixa3qEeBggOixFQBFWft
31 | 8wrkKTHpOQXjn4sDPtet8imm9UYEtzWrFX6T9MFYkBR0/yye0FIh9+YPiTA6WB86
32 | NCNwK5Yl6HuvF97CIH5CdgO+5C7KifUtqTOL8pQKbNwy0S3sNYvB+njGvRpR7pKV
33 | BUnFpB/Atptqr4CUlTXrc5IPLAqAfmwk5IKcwy3EXUbruf9Dwz69YA==
34 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/socks5-proxies.json:
--------------------------------------------------------------------------------
1 | {
2 | "Proxies": [
3 | "127.0.0.1:55555",
4 | "127.0.0.1:55556",
5 | "127.0.0.1:55557",
6 | "127.0.0.1:55558",
7 | "127.0.0.1:55559"
8 | ]
9 | }
--------------------------------------------------------------------------------
/useragents.json:
--------------------------------------------------------------------------------
1 | {
2 | "UserAgents": [
3 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
4 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0",
5 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
6 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
7 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15",
8 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
9 | "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0",
10 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
11 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
12 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0",
13 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
14 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
15 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:59.0) Gecko/20100101 Firefox/59.0",
16 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0.3 Safari/604.5.6",
17 | "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
18 | "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
19 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
20 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
21 | "Mozilla/5.0 (X11; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0",
22 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
23 | "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0",
24 | "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
25 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
26 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15",
27 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
28 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
29 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:59.0) Gecko/20100101 Firefox/59.0",
30 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/65.0.3325.181 Chrome/65.0.3325.181 Safari/537.36",
31 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
32 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
33 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
34 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0",
35 | "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0",
36 | "Mozilla/5.0 (Windows NT 6.1; rv:59.0) Gecko/20100101 Firefox/59.0",
37 | "Mozilla/5.0 (iPad; CPU OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1",
38 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0",
39 | "Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0",
40 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0",
41 | "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
42 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
43 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; Trident/5.0)",
44 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15",
45 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64",
46 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
47 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7",
48 | "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0",
49 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.40",
50 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
51 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Trident/5.0)",
52 | "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
53 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:59.0) Gecko/20100101 Firefox/59.0",
54 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
55 | "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko",
56 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
57 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0.3 Safari/604.5.6",
58 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36",
59 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
60 | "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0",
61 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
62 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36",
63 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5",
64 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0",
65 | "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0",
66 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
67 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36",
68 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393",
69 | "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0",
70 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0",
71 | "Mozilla/5.0 (iPad; CPU OS 11_2_6 like Mac OS X) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0 Mobile/15D100 Safari/604.1",
72 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0",
73 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8",
74 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
75 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
76 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
77 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36",
78 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0",
79 | "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko",
80 | "Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0",
81 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64",
82 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0",
83 | "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv11.0) like Gecko",
84 | "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36"
85 | ]
86 | }
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2010-2016 Google, Inc. http://angularjs.org
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
13 | all 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
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/README.md:
--------------------------------------------------------------------------------
1 | # SOCKS
2 | [](https://travis-ci.org/eahydra/socks) [](https://godoc.org/github.com/eahydra/socks)
3 |
4 | SOCKS implements SOCKS4/5 Proxy Protocol and HTTP Tunnel which can help you get through firewall.
5 | The [cmd/socksd](https://github.com/eahydra/socks/blob/master/cmd/socksd) build with package SOCKS, supports cipher connection which crypto method is rc4, des, aes-128-cfb, aes-192-cfb and aes-256-cfb, upstream which can be shadowsocks or socsk5.
6 |
7 | # Install
8 | Assume you have go installed, you can install from source.
9 | ```
10 | go get github.com/eahydra/socks
11 | ```
12 |
13 | If you want to install [cmd/socksd](https://github.com/eahydra/socks/blob/master/cmd/socksd), please read the [README.md](https://github.com/eahydra/socks/blob/master/cmd/socksd/README.md)
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/README.md:
--------------------------------------------------------------------------------
1 | # SOCKS
2 | [](https://travis-ci.org/eahydra/socks)
3 |
4 | The cmd/socksd build with package SOCKS, supports cipher connection which crypto method is rc4, des, aes-128-cfb, aes-192-cfb and aes-256-cfb, upstream which can be shadowsocks or socsk5.
5 |
6 | # Install
7 | Assume you have go installed, you can install from source.
8 | ```
9 | go get github.com/eahydra/socks/cmd/socksd
10 | ```
11 |
12 | # Usage
13 | Configuration file is in json format. The file must name **socks.config** and put it with socksd together.
14 | Configuration parameters as follows:
15 | ```json
16 | {
17 | "pac":{
18 | "address":"127.0.0.1:50000",
19 | "proxy":"127.0.0.1:40000",
20 | "socks5":"127.0.0.1:8000",
21 | "local_rule_file":"gfw.txt",
22 | "remote_rule_file":"https://raw.githubusercontent.com/Leask/BRICKS/master/gfw.bricks",
23 | "upstream":{
24 | "type":"shadowsocks",
25 | "crypto": "aes-256-cfb",
26 | "password": "111222333",
27 | "address": "106.182.12.24:10089"
28 | }
29 | },
30 | "proxies":[
31 | {
32 | "http":":40000",
33 | "socks4": ":9000",
34 | "socks5": ":8000",
35 | "upstreams": [
36 | {
37 | "type":"shadowsocks",
38 | "crypto": "aes-256-cfb",
39 | "password": "111222333",
40 | "address": "106.182.12.24:10089"
41 | }
42 | ]
43 | }
44 | ]
45 | }
46 |
47 | ```
48 |
49 | * **pac** - PAC config
50 | * **address** - Specifies the PAC server (127.0.0.1:50000)
51 | * **proxy** - (OPTIONAL) Enable HTTP Proxy in PAC
52 | * **socks5** - (OPTIONAL) Enable SOCKS5 Proxy in PAC
53 | * **local_rule_file** - (OPTIONAL) Local PAC rule file that per line is domain
54 | * **remote_rule_file** - (OPTIONAL) Remote PAC rule file like as [bricks](https://raw.githubusercontent.com/Leask/BRICKS/master/gfw.bricks)
55 | * **upstream** - (OPTIONAL) Through upstream to get **remote_rule_file**
56 | * **proxies** - The array of proxy config item
57 | * **http** - (OPTIONAL) Enable http proxy tunnel (127.0.0.1:8080 or :8080)
58 | * **socks4** - (OPTIONAL) Enable SOCKS4 proxy (127.0.0.1:9090 or :9090)
59 | * **socks5** - (OPTIONAL) Enable SOCKS5 proxy (127.0.0.1:9999 or :9999)
60 | * **crypto** - (OPTIONAL) SOCKS5's crypto method, now supports rc4, des, aes-128-cfb, aes-192-cfb and aes-256-cfb
61 | * **password** - If you set **crypto**, you must also set passsword
62 | * **dnsCacheTimeout** - (OPTIONAL) Enable dns cache (unit is second)
63 | * **upstreams** - The array of **upstream**
64 | * **upstream**
65 | * **type** - Specifies the type of upstream proxy server. Now supports shadowsocks and socks5
66 | * **crypto** - Specifies the crypto method of upstream proxy server. The crypto method is same as **localCryptoMethod**
67 | * **password** - Specifies the crypto password of upstream proxy server
68 | * **address** - Specifies the address of upstream proxy server (8.8.8.8:1111)
69 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/cipher.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/cipher"
6 | "crypto/des"
7 | "crypto/md5"
8 | "crypto/rand"
9 | "crypto/rc4"
10 | "io"
11 |
12 | "github.com/codahale/chacha20"
13 | )
14 |
15 | func md5sum(d []byte) []byte {
16 | h := md5.New()
17 | h.Write(d)
18 | return h.Sum(nil)
19 | }
20 |
21 | func evpBytesToKey(password []byte, keylen int) (key []byte) {
22 | const md5len = 16
23 | cnt := (keylen-1)/md5len + 1
24 | m := make([]byte, cnt*md5len)
25 | copy(m, md5sum(password))
26 |
27 | d := make([]byte, md5len+len(password))
28 | start := 0
29 | for i := 1; i < cnt; i++ {
30 | start += md5len
31 | copy(d, m[start-md5len:start])
32 | copy(d[md5len:], password)
33 | copy(m[start:], md5sum(d))
34 | }
35 | return m[:keylen]
36 | }
37 |
38 | type RC4Cipher struct {
39 | *cipher.StreamReader
40 | *cipher.StreamWriter
41 | }
42 |
43 | func NewRC4Cipher(rwc io.ReadWriteCloser, password []byte) (*RC4Cipher, error) {
44 | decryptCipher, err := rc4.NewCipher(password)
45 | if err != nil {
46 | return nil, err
47 | }
48 | encryptCipher, err := rc4.NewCipher(password)
49 | if err != nil {
50 | return nil, err
51 | }
52 | return &RC4Cipher{
53 | StreamReader: &cipher.StreamReader{
54 | S: decryptCipher,
55 | R: rwc,
56 | },
57 | StreamWriter: &cipher.StreamWriter{
58 | S: encryptCipher,
59 | W: rwc,
60 | },
61 | }, nil
62 | }
63 |
64 | type Chacha20Cipher struct {
65 | password []byte
66 | rwc io.ReadWriteCloser
67 | *cipher.StreamReader
68 | *cipher.StreamWriter
69 | }
70 |
71 | func NewChacha20Cipher(rwc io.ReadWriteCloser, password []byte) (*Chacha20Cipher, error) {
72 | password = evpBytesToKey(password, chacha20.KeySize)
73 | return &Chacha20Cipher{
74 | rwc: rwc,
75 | password: password,
76 | }, nil
77 | }
78 |
79 | func (c *Chacha20Cipher) Read(p []byte) (n int, err error) {
80 | if c.StreamReader == nil {
81 | iv := make([]byte, chacha20.NonceSize)
82 | n, err = io.ReadFull(c.rwc, iv)
83 | if err != nil {
84 | return n, err
85 | }
86 | stream, err := chacha20.New(c.password, iv)
87 | if err != nil {
88 | return n, err
89 | }
90 |
91 | c.StreamReader = &cipher.StreamReader{
92 | S: stream,
93 | R: c.rwc,
94 | }
95 | }
96 | return c.StreamReader.Read(p)
97 | }
98 |
99 | func (c *Chacha20Cipher) Write(p []byte) (n int, err error) {
100 | if c.StreamWriter == nil {
101 | iv := make([]byte, chacha20.NonceSize)
102 | _, err = rand.Read(iv)
103 | if err != nil {
104 | return 0, err
105 | }
106 | stream, err := chacha20.New(c.password, iv)
107 | if err != nil {
108 | return n, err
109 | }
110 | c.StreamWriter = &cipher.StreamWriter{
111 | S: stream,
112 | W: c.rwc,
113 | }
114 | n, err := c.rwc.Write(iv)
115 | if err != nil {
116 | return n, err
117 | }
118 | }
119 | return c.StreamWriter.Write(p)
120 | }
121 |
122 | type DESCFBCipher struct {
123 | block cipher.Block
124 | rwc io.ReadWriteCloser
125 | *cipher.StreamReader
126 | *cipher.StreamWriter
127 | }
128 |
129 | func NewDESCFBCipher(rwc io.ReadWriteCloser, password []byte) (*DESCFBCipher, error) {
130 | block, err := des.NewCipher(password)
131 | if err != nil {
132 | return nil, err
133 | }
134 |
135 | return &DESCFBCipher{
136 | block: block,
137 | rwc: rwc,
138 | }, nil
139 | }
140 |
141 | func (d *DESCFBCipher) Read(p []byte) (n int, err error) {
142 | if d.StreamReader == nil {
143 | iv := make([]byte, d.block.BlockSize())
144 | n, err = io.ReadFull(d.rwc, iv)
145 | if err != nil {
146 | return n, err
147 | }
148 | stream := cipher.NewCFBDecrypter(d.block, iv)
149 | d.StreamReader = &cipher.StreamReader{
150 | S: stream,
151 | R: d.rwc,
152 | }
153 | }
154 | return d.StreamReader.Read(p)
155 | }
156 |
157 | func (d *DESCFBCipher) Write(p []byte) (n int, err error) {
158 | if d.StreamWriter == nil {
159 | iv := make([]byte, d.block.BlockSize())
160 | _, err = rand.Read(iv)
161 | if err != nil {
162 | return 0, err
163 | }
164 | stream := cipher.NewCFBEncrypter(d.block, iv)
165 | d.StreamWriter = &cipher.StreamWriter{
166 | S: stream,
167 | W: d.rwc,
168 | }
169 | n, err := d.rwc.Write(iv)
170 | if err != nil {
171 | return n, err
172 | }
173 | }
174 | return d.StreamWriter.Write(p)
175 | }
176 |
177 | func (d *DESCFBCipher) Close() error {
178 | if d.StreamWriter != nil {
179 | d.StreamWriter.Close()
180 | }
181 | if d.rwc != nil {
182 | d.rwc.Close()
183 | }
184 | return nil
185 | }
186 |
187 | type AESCFBCipher struct {
188 | rwc io.ReadWriteCloser
189 | iv []byte
190 | block cipher.Block
191 | *cipher.StreamReader
192 | *cipher.StreamWriter
193 | }
194 |
195 | func NewAESCFGCipher(rwc io.ReadWriteCloser, password []byte, bit int) (*AESCFBCipher, error) {
196 | block, err := aes.NewCipher(evpBytesToKey(password, bit))
197 | if err != nil {
198 | return nil, err
199 | }
200 | return &AESCFBCipher{
201 | block: block,
202 | rwc: rwc,
203 | }, nil
204 | }
205 |
206 | func (a *AESCFBCipher) Read(p []byte) (n int, err error) {
207 | if a.StreamReader == nil {
208 | iv := make([]byte, a.block.BlockSize())
209 | n, err = io.ReadFull(a.rwc, iv)
210 | if err != nil {
211 | return n, err
212 | }
213 | stream := cipher.NewCFBDecrypter(a.block, iv)
214 | a.StreamReader = &cipher.StreamReader{
215 | S: stream,
216 | R: a.rwc,
217 | }
218 | }
219 | return a.StreamReader.Read(p)
220 | }
221 |
222 | func (a *AESCFBCipher) Write(p []byte) (n int, err error) {
223 | if a.StreamWriter == nil {
224 | iv := make([]byte, a.block.BlockSize())
225 | _, err = rand.Read(iv)
226 | if err != nil {
227 | return 0, err
228 | }
229 | stream := cipher.NewCFBEncrypter(a.block, iv)
230 | a.StreamWriter = &cipher.StreamWriter{
231 | S: stream,
232 | W: a.rwc,
233 | }
234 | n, err := a.rwc.Write(iv)
235 | if err != nil {
236 | return n, err
237 | }
238 | }
239 | return a.StreamWriter.Write(p)
240 | }
241 |
242 | func (a *AESCFBCipher) Close() error {
243 | if a.StreamWriter != nil {
244 | a.StreamWriter.Close()
245 | }
246 | if a.rwc != nil {
247 | a.rwc.Close()
248 | }
249 | return nil
250 | }
251 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/cipher_conn.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "io"
5 | "net"
6 | "strings"
7 | )
8 |
9 | type CipherConn struct {
10 | net.Conn
11 | rwc io.ReadWriteCloser
12 | }
13 |
14 | func (c *CipherConn) Read(data []byte) (int, error) {
15 | return c.rwc.Read(data)
16 | }
17 |
18 | func (c *CipherConn) Write(data []byte) (int, error) {
19 | return c.rwc.Write(data)
20 | }
21 |
22 | func (c *CipherConn) Close() error {
23 | err := c.Conn.Close()
24 | c.rwc.Close()
25 | return err
26 | }
27 |
28 | func NewCipherConn(conn net.Conn, cryptMethod string, password []byte) (*CipherConn, error) {
29 | var rwc io.ReadWriteCloser
30 | var err error
31 | switch strings.ToLower(cryptMethod) {
32 | default:
33 | rwc = conn
34 | case "rc4":
35 | rwc, err = NewRC4Cipher(conn, password)
36 | case "des":
37 | rwc, err = NewDESCFBCipher(conn, password)
38 | case "aes-128-cfb":
39 | rwc, err = NewAESCFGCipher(conn, password, 16)
40 | case "aes-192-cfb":
41 | rwc, err = NewAESCFGCipher(conn, password, 24)
42 | case "aes-256-cfb":
43 | rwc, err = NewAESCFGCipher(conn, password, 32)
44 | case "chacha20":
45 | rwc, err = NewChacha20Cipher(conn, password)
46 | }
47 | if err != nil {
48 | return nil, err
49 | }
50 |
51 | return &CipherConn{
52 | Conn: conn,
53 | rwc: rwc,
54 | }, nil
55 | }
56 |
57 | func NewCipherConnDecorator(cryptoMethod, password string) ConnDecorator {
58 | return func(conn net.Conn) (net.Conn, error) {
59 | return NewCipherConn(conn, cryptoMethod, []byte(password))
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/config.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "io/ioutil"
6 | )
7 |
8 | type Upstream struct {
9 | Type string `json:"type"`
10 | Crypto string `json:"crypto"`
11 | Password string `json:"password"`
12 | Address string `json:"address"`
13 | }
14 |
15 | type PAC struct {
16 | Address string `json:"address"`
17 | Proxy string `json:"proxy"`
18 | SOCKS5 string `json:"socks5"`
19 | LocalRules string `json:"local_rule_file"`
20 | RemoteRules string `json:"remote_rule_file"`
21 | Upstream Upstream `json:"upstream"`
22 | }
23 |
24 | type Proxy struct {
25 | HTTP string `json:"http"`
26 | SOCKS4 string `json:"socks4"`
27 | SOCKS5 string `json:"socks5"`
28 | Crypto string `json:"crypto"`
29 | Password string `json:"password"`
30 | DNSCacheTimeout int `json:"dnsCacheTimeout"`
31 | Upstreams []Upstream `json:"upstreams"`
32 | }
33 |
34 | type Config struct {
35 | PAC PAC `json:"pac"`
36 | Proxies []Proxy `json:"proxies"`
37 | }
38 |
39 | func LoadConfig(s string) (*Config, error) {
40 | data, err := ioutil.ReadFile(s)
41 | if err != nil {
42 | return nil, err
43 | }
44 | cfgGroup := &Config{}
45 | if err = json.Unmarshal(data, cfgGroup); err != nil {
46 | return nil, err
47 | }
48 | return cfgGroup, nil
49 | }
50 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/decorate_client.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net"
5 |
6 | "github.com/eahydra/socks"
7 | )
8 |
9 | type DecorateClient struct {
10 | forward socks.Dialer
11 | decorators []ConnDecorator
12 | }
13 |
14 | func NewDecorateClient(forward socks.Dialer, ds ...ConnDecorator) *DecorateClient {
15 | d := &DecorateClient{
16 | forward: forward,
17 | }
18 | d.decorators = append(d.decorators, ds...)
19 | return d
20 | }
21 |
22 | func (d *DecorateClient) Dial(network, address string) (net.Conn, error) {
23 | conn, err := d.forward.Dial(network, address)
24 | if err != nil {
25 | ErrLog.Println("DecorateClient forward.Dial failed, err:", err, address)
26 | return nil, err
27 | }
28 | dconn, err := DecorateConn(conn, d.decorators...)
29 | if err != nil {
30 | conn.Close()
31 | return nil, err
32 | }
33 | return dconn, nil
34 | }
35 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/decorate_conn.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net"
4 |
5 | type ConnDecorator func(net.Conn) (net.Conn, error)
6 |
7 | func DecorateConn(conn net.Conn, ds ...ConnDecorator) (net.Conn, error) {
8 | decorated := conn
9 | var err error
10 | for _, decorate := range ds {
11 | decorated, err = decorate(decorated)
12 | if err != nil {
13 | return nil, err
14 | }
15 | }
16 | return decorated, nil
17 | }
18 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/decorate_direct.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net"
5 |
6 | "github.com/eahydra/socks"
7 | )
8 |
9 | type DecorateDirect struct {
10 | dnsCache *DNSCache
11 | }
12 |
13 | func NewDecorateDirect(dnsCacheTime int) *DecorateDirect {
14 | var dnsCache *DNSCache
15 | if dnsCacheTime != 0 {
16 | dnsCache = NewDNSCache(dnsCacheTime)
17 | }
18 | return &DecorateDirect{
19 | dnsCache: dnsCache,
20 | }
21 | }
22 |
23 | func parseAddress(address string) (interface{}, string, error) {
24 | host, port, err := net.SplitHostPort(address)
25 | if err != nil {
26 | return nil, "", err
27 | }
28 | ip := net.ParseIP(address)
29 | if ip != nil {
30 | return ip, port, nil
31 | } else {
32 | return host, port, nil
33 | }
34 | }
35 |
36 | func (d *DecorateDirect) Dial(network, address string) (net.Conn, error) {
37 | host, port, err := parseAddress(address)
38 | if err != nil {
39 | return nil, err
40 | }
41 | var dest string
42 | var ipCached bool
43 | switch h := host.(type) {
44 | case net.IP:
45 | {
46 | dest = h.String()
47 | ipCached = true
48 | }
49 | case string:
50 | {
51 | dest = h
52 | if d.dnsCache != nil {
53 | if p, ok := d.dnsCache.Get(h); ok {
54 | dest = p.String()
55 | ipCached = true
56 | }
57 | }
58 | }
59 | }
60 | address = net.JoinHostPort(dest, port)
61 | destConn, err := socks.Direct.Dial(network, address)
62 | if err != nil {
63 | return nil, err
64 | }
65 |
66 | if d.dnsCache != nil && !ipCached {
67 | d.dnsCache.Set(host.(string), destConn.RemoteAddr().(*net.TCPAddr).IP)
68 | }
69 | return destConn, nil
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/decorate_listener.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net"
4 |
5 | type DecorateListener struct {
6 | listener net.Listener
7 | decorators []ConnDecorator
8 | }
9 |
10 | func NewDecorateListener(listener net.Listener, ds ...ConnDecorator) *DecorateListener {
11 | l := &DecorateListener{
12 | listener: listener,
13 | }
14 | l.decorators = append(l.decorators, ds...)
15 | return l
16 | }
17 |
18 | func (s *DecorateListener) Accept() (net.Conn, error) {
19 | conn, err := s.listener.Accept()
20 | if err != nil {
21 | return nil, err
22 | }
23 | dconn, err := DecorateConn(conn, s.decorators...)
24 | if err != nil {
25 | conn.Close()
26 | return nil, err
27 | }
28 | return dconn, nil
29 | }
30 |
31 | func (s *DecorateListener) Close() error {
32 | return s.listener.Close()
33 | }
34 |
35 | func (s *DecorateListener) Addr() net.Addr {
36 | return s.listener.Addr()
37 | }
38 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/dns_cache.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net"
5 | "sync"
6 | "time"
7 | )
8 |
9 | type DNSCache struct {
10 | lock sync.RWMutex
11 | cacheTimeout time.Duration
12 | dns map[string]DNSElement
13 | }
14 |
15 | type DNSElement struct {
16 | ip net.IP
17 | startTime time.Time
18 | }
19 |
20 | func NewDNSCache(cacheTimeout int) *DNSCache {
21 | if cacheTimeout <= 0 {
22 | cacheTimeout = 30
23 | }
24 | return &DNSCache{
25 | cacheTimeout: time.Duration(cacheTimeout) * time.Minute,
26 | dns: make(map[string]DNSElement),
27 | }
28 | }
29 |
30 | func (c *DNSCache) Get(domain string) (net.IP, bool) {
31 | c.lock.RLock()
32 | e, ok := c.dns[domain]
33 | c.lock.RUnlock()
34 | if ok && time.Since(e.startTime) > c.cacheTimeout {
35 | c.lock.Lock()
36 | delete(c.dns, domain)
37 | c.lock.Unlock()
38 | return nil, false
39 | }
40 | return e.ip, ok
41 | }
42 |
43 | func (c *DNSCache) Set(domain string, ip net.IP) {
44 | c.lock.Lock()
45 | c.dns[domain] = DNSElement{ip: ip, startTime: time.Now()}
46 | c.lock.Unlock()
47 | }
48 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/log.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | )
7 |
8 | var (
9 | InfoLog = log.New(os.Stdout, "INFO ", log.LstdFlags)
10 | ErrLog = log.New(os.Stderr, "ERROR ", log.LstdFlags)
11 | WarnLog = log.New(os.Stdout, "WARN ", log.LstdFlags)
12 | )
13 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "flag"
7 | "net"
8 | "net/http"
9 | "os"
10 | "os/signal"
11 | "strings"
12 |
13 | "github.com/eahydra/socks"
14 | )
15 |
16 | func main() {
17 | var configFile string
18 | flag.StringVar(&configFile, "c", "socks.config", "config file path")
19 | flag.Parse()
20 |
21 | conf, err := LoadConfig(configFile)
22 | if err != nil {
23 | ErrLog.Println("initGlobalConfig failed, err:", err)
24 | return
25 | }
26 | InfoLog.Println("load config succeeded")
27 |
28 | for _, c := range conf.Proxies {
29 | router := BuildUpstreamRouter(c)
30 | runHTTPProxyServer(c, router)
31 | runSOCKS4Server(c, router)
32 | runSOCKS5Server(c, router)
33 | }
34 | runPACServer(conf.PAC)
35 |
36 | sigChan := make(chan os.Signal, 1)
37 | signal.Notify(sigChan, os.Kill, os.Interrupt)
38 | <-sigChan
39 | }
40 |
41 | func BuildUpstream(upstream Upstream, forward socks.Dialer) (socks.Dialer, error) {
42 | cipherDecorator := NewCipherConnDecorator(upstream.Crypto, upstream.Password)
43 | forward = NewDecorateClient(forward, cipherDecorator)
44 |
45 | switch strings.ToLower(upstream.Type) {
46 | case "socks5":
47 | {
48 | return socks.NewSocks5Client("tcp", upstream.Address, "", "", forward)
49 | }
50 | case "shadowsocks":
51 | {
52 | return socks.NewShadowSocksClient("tcp", upstream.Address, forward)
53 | }
54 | }
55 | return nil, errors.New("unknown upstream type" + upstream.Type)
56 | }
57 |
58 | func BuildUpstreamRouter(conf Proxy) socks.Dialer {
59 | var allForward []socks.Dialer
60 | for _, upstream := range conf.Upstreams {
61 | var forward socks.Dialer
62 | var err error
63 | forward = NewDecorateDirect(conf.DNSCacheTimeout)
64 | forward, err = BuildUpstream(upstream, forward)
65 | if err != nil {
66 | ErrLog.Println("failed to BuildUpstream, err:", err)
67 | continue
68 | }
69 | allForward = append(allForward, forward)
70 | }
71 | if len(allForward) == 0 {
72 | router := NewDecorateDirect(conf.DNSCacheTimeout)
73 | allForward = append(allForward, router)
74 | }
75 | return NewUpstreamDialer(allForward)
76 | }
77 |
78 | func runHTTPProxyServer(conf Proxy, router socks.Dialer) {
79 | if conf.HTTP != "" {
80 | listener, err := net.Listen("tcp", conf.HTTP)
81 | if err != nil {
82 | ErrLog.Println("net.Listen at ", conf.HTTP, " failed, err:", err)
83 | return
84 | }
85 | go func() {
86 | defer listener.Close()
87 | httpProxy := socks.NewHTTPProxy(router)
88 | http.Serve(listener, httpProxy)
89 | }()
90 | }
91 | }
92 |
93 | func runSOCKS4Server(conf Proxy, forward socks.Dialer) {
94 | if conf.SOCKS4 != "" {
95 | listener, err := net.Listen("tcp", conf.SOCKS4)
96 | if err != nil {
97 | ErrLog.Println("net.Listen failed, err:", err, conf.SOCKS4)
98 | return
99 | }
100 | cipherDecorator := NewCipherConnDecorator(conf.Crypto, conf.Password)
101 | listener = NewDecorateListener(listener, cipherDecorator)
102 | socks4Svr, err := socks.NewSocks4Server(forward)
103 | if err != nil {
104 | listener.Close()
105 | ErrLog.Println("socks.NewSocks4Server failed, err:", err)
106 | }
107 | go func() {
108 | defer listener.Close()
109 | socks4Svr.Serve(listener)
110 | }()
111 | }
112 | }
113 |
114 | func runSOCKS5Server(conf Proxy, forward socks.Dialer) {
115 | if conf.SOCKS5 != "" {
116 | listener, err := net.Listen("tcp", conf.SOCKS5)
117 | if err != nil {
118 | ErrLog.Println("net.Listen failed, err:", err, conf.SOCKS5)
119 | return
120 | }
121 | cipherDecorator := NewCipherConnDecorator(conf.Crypto, conf.Password)
122 | listener = NewDecorateListener(listener, cipherDecorator)
123 | socks5Svr, err := socks.NewSocks5Server(forward)
124 | if err != nil {
125 | listener.Close()
126 | ErrLog.Println("socks.NewSocks5Server failed, err:", err)
127 | return
128 | }
129 | go func() {
130 | defer listener.Close()
131 | socks5Svr.Serve(listener)
132 | }()
133 | }
134 | }
135 |
136 | func runPACServer(pac PAC) {
137 | pu, err := NewPACUpdater(pac)
138 | if err != nil {
139 | ErrLog.Println("failed to NewPACUpdater, err:", err)
140 | return
141 | }
142 |
143 | http.HandleFunc("/proxy.pac", func(w http.ResponseWriter, r *http.Request) {
144 | w.Header().Add("Content-Type", "application/x-ns-proxy-autoconfig")
145 | data, time := pu.get()
146 | reader := bytes.NewReader(data)
147 | http.ServeContent(w, r, "proxy.pac", time, reader)
148 | })
149 | go http.ListenAndServe(pac.Address, nil)
150 | }
151 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/pac_generator.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "sort"
7 | "text/template"
8 | )
9 |
10 | var pacTemplate = `
11 | var proxy = "{{if .Socks5}}SOCKS5 {{.Socks5}};{{end}}{{if .Proxy}}PROXY {{.Proxy}}{{end}};";
12 |
13 | var domains = {
14 | {{.Rules}}
15 | };
16 |
17 | var hasOwnProperty = Object.hasOwnProperty;
18 |
19 | function FindProxyForURL(url, host) {
20 | if (isPlainHostName(host) || host === '127.0.0.1' || host === 'localhost') {
21 | return 'DIRECT';
22 | }
23 | var suffix;
24 | var pos = host.lastIndexOf('.');
25 | while(1) {
26 | suffix = host.substring(pos + 1);
27 | if (hasOwnProperty.call(domains, suffix)) {
28 | return proxy;
29 | }
30 | if (pos <= 0) {
31 | break;
32 | }
33 | pos = host.lastIndexOf('.', pos - 1);
34 | }
35 | return 'DIRECT';
36 | }
37 | `
38 |
39 | type PACGenerator struct {
40 | filter map[string]bool
41 | rules []string
42 | proxy string
43 | socks5 string
44 | }
45 |
46 | func NewPACGenerator(proxy, socks5 string) *PACGenerator {
47 | return &PACGenerator{
48 | filter: make(map[string]bool),
49 | proxy: proxy,
50 | socks5: socks5,
51 | }
52 | }
53 |
54 | func (p *PACGenerator) Generate(rules []string) ([]byte, error) {
55 | for _, v := range rules {
56 | if _, ok := p.filter[v]; !ok {
57 | p.filter[v] = true
58 | p.rules = append(p.rules, v)
59 | }
60 | }
61 | sort.Strings(p.rules)
62 |
63 | s := ""
64 | for n, v := range p.rules {
65 | s += fmt.Sprintf("'%s' : 1", v)
66 | if n+1 != len(p.rules) {
67 | s += ","
68 | }
69 | }
70 |
71 | data := struct {
72 | Proxy string
73 | Socks5 string
74 | Rules string
75 | }{
76 | Proxy: p.proxy,
77 | Socks5: p.socks5,
78 | Rules: s,
79 | }
80 | t, err := template.New("proxy.pac").Parse(pacTemplate)
81 | if err != nil {
82 | ErrLog.Println("failed to parse pacTempalte, err:", err)
83 | }
84 | buff := bytes.NewBuffer(nil)
85 | err = t.Execute(buff, &data)
86 | if err != nil {
87 | return nil, err
88 | }
89 | return buff.Bytes(), nil
90 | }
91 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/pac_updater.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "io"
6 | "net/http"
7 | "os"
8 | "sync"
9 | "time"
10 |
11 | "github.com/eahydra/socks"
12 | )
13 |
14 | type PACUpdater struct {
15 | pac PAC
16 | lock sync.RWMutex
17 | data []byte
18 | modtime time.Time
19 | timer *time.Timer
20 | }
21 |
22 | func NewPACUpdater(pac PAC) (*PACUpdater, error) {
23 | p := &PACUpdater{
24 | pac: pac,
25 | }
26 | go p.backgroundUpdate()
27 | return p, nil
28 | }
29 |
30 | func parseRule(reader io.Reader) ([]string, error) {
31 | var err error
32 | var line []byte
33 | var rules []string
34 | r := bufio.NewReader(reader)
35 | for line, _, err = r.ReadLine(); err == nil; line, _, err = r.ReadLine() {
36 | s := string(line)
37 | if s != "" {
38 | rules = append(rules, s)
39 | }
40 | }
41 | if err == io.EOF {
42 | err = nil
43 | }
44 | return rules, err
45 | }
46 |
47 | func loadLocalRule(filepath string) ([]string, error) {
48 | f, err := os.OpenFile(filepath, os.O_RDONLY, os.ModePerm)
49 | if err != nil {
50 | return nil, err
51 | }
52 | defer f.Close()
53 | return parseRule(f)
54 | }
55 |
56 | func loadRemoteRule(ruleURL string, upstream Upstream) ([]string, error) {
57 | forward, err := BuildUpstream(upstream, socks.Direct)
58 | if err != nil {
59 | return nil, err
60 | }
61 | client := &http.Client{
62 | Transport: &http.Transport{
63 | Dial: forward.Dial,
64 | },
65 | }
66 | resp, err := client.Get(ruleURL)
67 | if err != nil {
68 | return nil, err
69 | }
70 | defer resp.Body.Close()
71 | return parseRule(resp.Body)
72 | }
73 |
74 | func (p *PACUpdater) get() ([]byte, time.Time) {
75 | p.lock.RLock()
76 | defer p.lock.RUnlock()
77 | d := make([]byte, len(p.data))
78 | copy(d, p.data)
79 | return d, p.modtime
80 | }
81 |
82 | func (p *PACUpdater) set(data []byte) {
83 | p.lock.Lock()
84 | defer p.lock.Unlock()
85 | p.data = make([]byte, len(data))
86 | copy(p.data, data)
87 | p.modtime = time.Now()
88 | }
89 |
90 | func (p *PACUpdater) backgroundUpdate() {
91 | pg := NewPACGenerator(p.pac.Proxy, p.pac.SOCKS5)
92 | for {
93 | duration := 1 * time.Minute
94 | if rules, err := loadLocalRule(p.pac.LocalRules); err == nil {
95 | if data, err := pg.Generate(rules); err == nil {
96 | p.set(data)
97 | InfoLog.Println("update rules from", p.pac.LocalRules, "succeeded")
98 | }
99 | }
100 |
101 | if rules, err := loadRemoteRule(p.pac.RemoteRules, p.pac.Upstream); err == nil {
102 | if data, err := pg.Generate(rules); err == nil {
103 | p.set(data)
104 | duration = 1 * time.Hour
105 | InfoLog.Println("update rules from", p.pac.RemoteRules, "succeeded")
106 | }
107 | }
108 | time.Sleep(duration)
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/cmd/socksd/upstream_client.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net"
5 | "sync/atomic"
6 |
7 | "github.com/eahydra/socks"
8 | )
9 |
10 | type UpstreamDialer struct {
11 | nextRouter uint64
12 | forwardDialers []socks.Dialer
13 | }
14 |
15 | func NewUpstreamDialer(forwardDialers []socks.Dialer) *UpstreamDialer {
16 | return &UpstreamDialer{
17 | forwardDialers: forwardDialers,
18 | }
19 | }
20 |
21 | func (u *UpstreamDialer) getNextDialer() socks.Dialer {
22 | old := atomic.AddUint64(&u.nextRouter, 1)
23 | return u.forwardDialers[old%uint64(len(u.forwardDialers))]
24 | }
25 |
26 | func (u *UpstreamDialer) Dial(network, address string) (net.Conn, error) {
27 | router := u.getNextDialer()
28 | conn, err := router.Dial(network, address)
29 | if err != nil {
30 | ErrLog.Println("UpstreamDialer router.Dial failed, err:", err, network, address)
31 | return nil, err
32 | }
33 | return conn, nil
34 | }
35 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/direct.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import "net"
4 |
5 | // A Dialer is a means to establish a connection.
6 | type Dialer interface {
7 | // Dial connects to the given address via the proxy.
8 | Dial(network, address string) (net.Conn, error)
9 | }
10 |
11 | type direct struct{}
12 |
13 | // Direct is a direct proxy which implements Dialer interface: one that makes connections directly.
14 | var Direct = direct{}
15 |
16 | func (direct) Dial(network, address string) (net.Conn, error) {
17 | return net.Dial(network, address)
18 | }
19 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/example_test.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "net"
5 | "net/http"
6 | "net/http/httputil"
7 | )
8 |
9 | func ExampleSocks5Client() {
10 | user := ""
11 | password := ""
12 | client, err := NewSocks5Client("tcp", "127.0.0.1:1080", user, password, Direct)
13 | if err != nil {
14 | return
15 | }
16 | conn, err := client.Dial("tcp", "www.google.com:80")
17 | if err != nil {
18 | return
19 | }
20 | httpClient := httputil.NewClientConn(conn, nil)
21 | defer httpClient.Close()
22 |
23 | request, err := http.NewRequest("GET", "/", nil)
24 | if err != nil {
25 | return
26 | }
27 | resp, err := httpClient.Do(request)
28 | if err != nil {
29 | return
30 | }
31 | dump, err := httputil.DumpResponse(resp, true)
32 | if err != nil {
33 | return
34 | }
35 | println(string(dump))
36 | return
37 | }
38 |
39 | func ExampleSocks5Server() {
40 | listener, err := net.Listen("tcp", ":1080")
41 | if err != nil {
42 | return
43 | }
44 | defer listener.Close()
45 |
46 | if server, err := NewSocks5Server(Direct); err == nil {
47 | server.Serve(listener)
48 | }
49 | }
50 |
51 | func ExampleSocks4Client() {
52 | user := ""
53 | client, err := NewSocks4Client("tcp", "127.0.0.1:1080", user, Direct)
54 | if err != nil {
55 | return
56 | }
57 | addrs, err := net.LookupHost("www.google.com")
58 | if err != nil {
59 | return
60 | }
61 | if len(addrs) == 0 {
62 | return
63 | }
64 | conn, err := client.Dial("tcp", addrs[0]+":80")
65 | if err != nil {
66 | return
67 | }
68 | httpClient := httputil.NewClientConn(conn, nil)
69 | defer httpClient.Close()
70 |
71 | request, err := http.NewRequest("GET", "/", nil)
72 | if err != nil {
73 | return
74 | }
75 | resp, err := httpClient.Do(request)
76 | if err != nil {
77 | return
78 | }
79 | dump, err := httputil.DumpResponse(resp, true)
80 | if err != nil {
81 | return
82 | }
83 | println(string(dump))
84 | return
85 | }
86 |
87 | func ExampleSocks4Server() {
88 | listener, err := net.Listen("tcp", ":1080")
89 | if err != nil {
90 | return
91 | }
92 | defer listener.Close()
93 |
94 | if server, err := NewSocks4Server(Direct); err == nil {
95 | server.Serve(listener)
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/http_proxy.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "net"
7 | "net/http"
8 | "net/http/httputil"
9 | "net/url"
10 | )
11 |
12 | // HTTPProxy is an HTTP Handler that serve CONNECT method and
13 | // route request to proxy server by Router.
14 | type HTTPProxy struct {
15 | *httputil.ReverseProxy
16 | forward Dialer
17 | }
18 |
19 | // NewHTTPProxy constructs one HTTPProxy
20 | func NewHTTPProxy(forward Dialer) *HTTPProxy {
21 | return &HTTPProxy{
22 | ReverseProxy: &httputil.ReverseProxy{
23 | Director: director,
24 | Transport: &http.Transport{
25 | Dial: func(network, addr string) (net.Conn, error) {
26 | return forward.Dial(network, addr)
27 | },
28 | },
29 | },
30 | forward: forward,
31 | }
32 | }
33 |
34 | func director(request *http.Request) {
35 | u, err := url.Parse(request.RequestURI)
36 | if err != nil {
37 | return
38 | }
39 | request.RequestURI = u.RequestURI()
40 | v := request.Header.Get("Proxy-Connection")
41 | if v != "" {
42 | request.Header.Del("Proxy-Connection")
43 | request.Header.Del("Connection")
44 | request.Header.Add("Connection", v)
45 | }
46 | }
47 |
48 | // ServeHTTPTunnel serve incoming request with CONNECT method, then route data to proxy server
49 | func (h *HTTPProxy) ServeHTTPTunnel(response http.ResponseWriter, request *http.Request) {
50 | var conn net.Conn
51 | if hj, ok := response.(http.Hijacker); ok {
52 | var err error
53 | if conn, _, err = hj.Hijack(); err != nil {
54 | http.Error(response, err.Error(), http.StatusInternalServerError)
55 | return
56 | }
57 | } else {
58 | http.Error(response, "Hijacker failed", http.StatusInternalServerError)
59 | return
60 | }
61 | defer conn.Close()
62 |
63 | dest, err := h.forward.Dial("tcp", request.Host)
64 | if err != nil {
65 | fmt.Fprintf(conn, "HTTP/1.0 500 NewRemoteSocks failed, err:%s\r\n\r\n", err)
66 | return
67 | }
68 | defer dest.Close()
69 |
70 | if request.Body != nil {
71 | if _, err = io.Copy(dest, request.Body); err != nil {
72 | fmt.Fprintf(conn, "%d %s", http.StatusBadGateway, err.Error())
73 | return
74 | }
75 | }
76 | fmt.Fprintf(conn, "HTTP/1.0 200 Connection established\r\n\r\n")
77 |
78 | go func() {
79 | defer conn.Close()
80 | defer dest.Close()
81 | io.Copy(dest, conn)
82 | }()
83 | io.Copy(conn, dest)
84 | }
85 |
86 | // ServeHTTP implements HTTP Handler
87 | func (h *HTTPProxy) ServeHTTP(response http.ResponseWriter, request *http.Request) {
88 | if request.Method == "CONNECT" {
89 | h.ServeHTTPTunnel(response, request)
90 | } else {
91 | h.ReverseProxy.ServeHTTP(response, request)
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/shadowsocks_client.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "errors"
5 | "net"
6 | "strconv"
7 | )
8 |
9 | // ShadowSocksClient implements ShadowSocks Proxy Protocol
10 | type ShadowSocksClient struct {
11 | network string
12 | address string
13 | forward Dialer
14 | }
15 |
16 | // NewShadowSocksClient return a new ShadowSocksClient that implements Dialer interface.
17 | func NewShadowSocksClient(network, address string, forward Dialer) (*ShadowSocksClient, error) {
18 | return &ShadowSocksClient{
19 | network: network,
20 | address: address,
21 | forward: forward,
22 | }, nil
23 | }
24 |
25 | // Dial return a new net.Conn that through proxy server establish with address
26 | func (s *ShadowSocksClient) Dial(network, address string) (net.Conn, error) {
27 | switch network {
28 | case "tcp", "tcp4", "tcp6":
29 | default:
30 | return nil, errors.New("socks: no support ShadowSocks proxy connections of type: " + network)
31 | }
32 |
33 | host, portStr, err := net.SplitHostPort(address)
34 | if err != nil {
35 | return nil, err
36 | }
37 | port, err := strconv.Atoi(portStr)
38 | if err != nil {
39 | return nil, errors.New("socks: failed to parse port number:" + portStr)
40 | }
41 | if port < 1 || port > 0xffff {
42 | return nil, errors.New("socks5: port number out of range:" + portStr)
43 | }
44 |
45 | conn, err := s.forward.Dial(s.network, s.address)
46 | if err != nil {
47 | return nil, err
48 | }
49 | closeConn := &conn
50 | defer func() {
51 | if closeConn != nil {
52 | (*closeConn).Close()
53 | }
54 | }()
55 |
56 | buff := make([]byte, 0, 266)
57 | if ip := net.ParseIP(host); ip != nil {
58 | if ip4 := ip.To4(); ip4 != nil {
59 | buff = append(buff, 1)
60 | ip = ip4
61 | } else {
62 | buff = append(buff, 4)
63 | }
64 | buff = append(buff, ip...)
65 | } else {
66 | if len(host) > 255 {
67 | return nil, errors.New("socks: destination hostname too long: " + host)
68 | }
69 | buff = append(buff, 3)
70 | buff = append(buff, uint8(len(host)))
71 | buff = append(buff, host...)
72 | }
73 | buff = append(buff, uint8(port>>8), uint8(port))
74 |
75 | _, err = conn.Write(buff)
76 | if err != nil {
77 | return nil, err
78 | }
79 |
80 | closeConn = nil
81 | return conn, nil
82 | }
83 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/socks4.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "bufio"
5 | "errors"
6 | "fmt"
7 | "io"
8 | "net"
9 | "strconv"
10 | )
11 |
12 | const (
13 | socks4Version = 4
14 | socks4Connect = 1
15 | socks4Granted = 90
16 | socks4Rejected = 91
17 | socks4ConnectFailed = 92
18 | socks4UserIDInvalid = 93
19 | )
20 |
21 | var socks4Errors = []string{
22 | "",
23 | "request rejected or failed",
24 | "request rejected because SOCKS server cannot connect to identd on the client",
25 | "request rejected because the client program and identd report different user-ids",
26 | }
27 |
28 | // Socks4Server implements Socks4 Proxy Protocol(http://www.openssh.com/txt/socks4.protocol).
29 | // Just support CONNECT command.
30 | type Socks4Server struct {
31 | forward Dialer
32 | }
33 |
34 | // NewSocks4Server returns a new Socks4Server that can serve from new clients.
35 | func NewSocks4Server(forward Dialer) (*Socks4Server, error) {
36 | return &Socks4Server{
37 | forward: forward,
38 | }, nil
39 | }
40 |
41 | // Serve with net.Listener for clients.
42 | func (s *Socks4Server) Serve(listener net.Listener) error {
43 | for {
44 | conn, err := listener.Accept()
45 | if err != nil {
46 | if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
47 | continue
48 | } else {
49 | return err
50 | }
51 | }
52 |
53 | go serveSOCKS4Client(conn, s.forward)
54 | }
55 | }
56 |
57 | // Socks4Client implements Socks4 Proxy Protocol(http://www.openssh.com/txt/socks4.protocol).
58 | type Socks4Client struct {
59 | network string
60 | address string
61 | userID string
62 | forward Dialer
63 | }
64 |
65 | // NewSocks4Client return a new Socks4Client that implements Dialer interface.
66 | // network must be supported by forward, address is proxy server's address, userID can empty.
67 | func NewSocks4Client(network, address, userID string, forward Dialer) (*Socks4Client, error) {
68 | return &Socks4Client{
69 | network: network,
70 | address: address,
71 | userID: userID,
72 | forward: forward,
73 | }, nil
74 | }
75 |
76 | // Dial return a new net.Conn if succeeded. network must be tcp, tcp4 or tcp6, address only is IPV4.
77 | func (s *Socks4Client) Dial(network, address string) (net.Conn, error) {
78 | switch network {
79 | case "tcp", "tcp4", "tcp6":
80 | default:
81 | return nil, errors.New("socks: no support for SOCKS4 proxy connections of type:" + network)
82 | }
83 |
84 | host, portStr, err := net.SplitHostPort(address)
85 | if err != nil {
86 | return nil, err
87 | }
88 | port, err := strconv.Atoi(portStr)
89 | if err != nil {
90 | return nil, errors.New("socks: failed to parse port:" + portStr)
91 | }
92 | if port < 1 || port > 0xffff {
93 | return nil, errors.New("socks: port number out of range:" + portStr)
94 | }
95 | ip := net.ParseIP(host)
96 | if ip == nil {
97 | return nil, errors.New("socks: destination host invalid:" + host)
98 | }
99 | ip4 := ip.To4()
100 | if ip4 == nil {
101 | return nil, errors.New("socks:destination ip must be ipv4:" + host)
102 | }
103 |
104 | conn, err := s.forward.Dial(s.network, s.address)
105 | if err != nil {
106 | return nil, err
107 | }
108 | closeConn := &conn
109 | defer func() {
110 | if closeConn != nil {
111 | (*closeConn).Close()
112 | }
113 | }()
114 |
115 | buff := make([]byte, 0, 8+len(s.userID)+1)
116 | buff = append(buff, socks4Version, socks4Connect)
117 | buff = append(buff, byte(port>>8), byte(port))
118 | buff = append(buff, ip4...)
119 | if len(s.userID) != 0 {
120 | buff = append(buff, []byte(s.userID)...)
121 | }
122 | buff = append(buff, 0)
123 |
124 | if _, err := conn.Write(buff); err != nil {
125 | return nil, errors.New("socks: failed to write connect request to SOCKS4 server at: " + s.address + ": " + err.Error())
126 | }
127 | buff = buff[:8]
128 | if _, err := io.ReadFull(conn, buff); err != nil {
129 | return nil, errors.New("socks: failed to read connect reply from SOCKS4 server at: " + s.address + ": " + err.Error())
130 | }
131 | if buff[1] != socks4Granted {
132 | cd := int(buff[1]) - socks4Granted
133 | failure := "unknown error"
134 | if cd < len(socks4Errors) && cd >= 0 {
135 | failure = socks4Errors[cd]
136 | }
137 | return nil, errors.New("socks: SOCKS4 server at " + s.address + " failed to connect: " + failure)
138 | }
139 |
140 | closeConn = nil
141 | return conn, nil
142 | }
143 |
144 | func serveSOCKS4Client(conn net.Conn, forward Dialer) {
145 | defer conn.Close()
146 |
147 | reader := bufio.NewReader(conn)
148 | buff, err := reader.Peek(9)
149 | if err != nil {
150 | return
151 | }
152 | if buff[8] != 0 {
153 | if _, err = reader.ReadSlice(0); err != nil {
154 | return
155 | }
156 | }
157 |
158 | reply := make([]byte, 8)
159 | if buff[0] != socks4Version {
160 | reply[1] = socks4Rejected
161 | conn.Write(reply)
162 | return
163 | }
164 | if buff[1] != socks4Connect {
165 | reply[1] = socks4Rejected
166 | conn.Write(reply)
167 | return
168 | }
169 |
170 | port := uint16(buff[2])<<8 | uint16(buff[3])
171 | ip := buff[4:8]
172 |
173 | host := fmt.Sprintf("%d.%d.%d.%d:%d", ip[0], ip[1], ip[2], ip[3], port)
174 | dest, err := forward.Dial("tcp4", host)
175 | if err != nil {
176 | reply[1] = socks4ConnectFailed
177 | conn.Write(reply)
178 | return
179 | }
180 | defer dest.Close()
181 |
182 | reply[1] = socks4Granted
183 | if _, err = conn.Write(reply); err != nil {
184 | return
185 | }
186 |
187 | go func() {
188 | defer conn.Close()
189 | defer dest.Close()
190 | io.Copy(dest, conn)
191 | }()
192 | io.Copy(conn, dest)
193 | }
194 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/socks4_test.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "net"
5 | "net/http"
6 | "net/http/httputil"
7 | "testing"
8 | )
9 |
10 | const (
11 | TestSocks4ServerAddr = "127.0.0.1:8000"
12 | TestSocks4TargetDomain = "www.baidu.com"
13 | )
14 |
15 | func TestSocks4Client(t *testing.T) {
16 | listener, err := net.Listen("tcp", TestSocks4ServerAddr)
17 | if err != nil {
18 | t.Fatal(err)
19 | }
20 | defer listener.Close()
21 | go func() {
22 | server, err := NewSocks4Server(Direct)
23 | if err != nil {
24 | t.Fatal(err)
25 | }
26 | server.Serve(listener)
27 | }()
28 |
29 | client, err := NewSocks4Client("tcp", TestSocks4ServerAddr, "", Direct)
30 | if err != nil {
31 | t.Fatal(err)
32 | }
33 |
34 | addrs, err := net.LookupHost(TestSocks4TargetDomain)
35 | if err != nil {
36 | t.Fatal(err)
37 | }
38 | if len(addrs) == 0 {
39 | t.Fatal("net.LookupHost with " + TestSocks4TargetDomain + " result invalid")
40 | }
41 |
42 | conn, err := client.Dial("tcp", addrs[0]+":80")
43 | if err != nil {
44 | t.Fatal("socks4 client.Dial failed, err: " + err.Error())
45 | }
46 | t.Log("client.Dial succeeded")
47 | httpClient := httputil.NewClientConn(conn, nil)
48 | if err != nil {
49 | conn.Close()
50 | t.Fatal(err)
51 | }
52 | defer httpClient.Close()
53 |
54 | request, err := http.NewRequest("GET", "/", nil)
55 | if err != nil {
56 | t.Fatal(err)
57 | }
58 | resp, err := httpClient.Do(request)
59 | if err != nil {
60 | t.Fatal(err)
61 | }
62 | data, err := httputil.DumpResponse(resp, true)
63 | if err != nil {
64 | t.Fatal(err)
65 | }
66 | t.Log("socks4 HTTP Get:", string(data))
67 | }
68 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/socks5_client.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "errors"
5 | "io"
6 | "net"
7 | "strconv"
8 | )
9 |
10 | const (
11 | socks5Version = 5
12 |
13 | socks5AuthNone = 0
14 | socks5AuthPassword = 2
15 | socks5AuthNoAccept = 0xff
16 |
17 | socks5AuthPasswordVer = 1
18 |
19 | socks5Connect = 1
20 |
21 | socks5IP4 = 1
22 | socks5Domain = 3
23 | socks5IP6 = 4
24 | )
25 |
26 | const (
27 | socks5Success = 0
28 | socks5GeneralFailure = 1
29 | socks5ConnectNotAllowed = 2
30 | socks5NetworkUnreachable = 3
31 | socks5HostUnreachable = 4
32 | socks5ConnectionRefused = 5
33 | socks5TTLExpired = 6
34 | socks5CommandNotSupported = 7
35 | socks5AddressTypeNotSupported = 8
36 | )
37 |
38 | var socks5Errors = []string{
39 | "",
40 | "general SOCKS server failure",
41 | "connection not allowed by ruleset",
42 | "network unreachable",
43 | "Host unreachable",
44 | "Connection refused",
45 | "TTL expired",
46 | "Command not supported",
47 | "Address type not supported",
48 | }
49 |
50 | // Socks5Client implements Socks5 Proxy Protocol(RFC 1928) Client Protocol.
51 | // Just support CONNECT command, and support USERNAME/PASSWORD authentication methods(RFC 1929)
52 | type Socks5Client struct {
53 | network string
54 | address string
55 | user string
56 | password string
57 | forward Dialer
58 | }
59 |
60 | // NewSocks5Client return a new Socks5Client that implements Dialer interface.
61 | func NewSocks5Client(network, address, user, password string, forward Dialer) (*Socks5Client, error) {
62 | return &Socks5Client{
63 | network: network,
64 | address: address,
65 | user: user,
66 | password: password,
67 | forward: forward,
68 | }, nil
69 | }
70 |
71 | // Dial return a new net.Conn that through the CONNECT command to establish connections with proxy server.
72 | // address as RFC's requirements that can be IPV4, IPV6 and domain host, such as 8.8.8.8:999 or google.com:80
73 | func (s *Socks5Client) Dial(network, address string) (net.Conn, error) {
74 | switch network {
75 | case "tcp", "tcp4", "tcp6":
76 | default:
77 | return nil, errors.New("socks: no support for SOCKS5 proxy connections of type:" + network)
78 | }
79 |
80 | conn, err := s.forward.Dial(s.network, s.address)
81 | if err != nil {
82 | return nil, err
83 | }
84 | closeConn := &conn
85 | defer func() {
86 | if closeConn != nil {
87 | (*closeConn).Close()
88 | }
89 | }()
90 |
91 | host, portStr, err := net.SplitHostPort(address)
92 | if err != nil {
93 | return nil, err
94 | }
95 |
96 | // check port
97 | port, err := strconv.Atoi(portStr)
98 | if err != nil {
99 | return nil, errors.New("socks: failed to parse port number: " + portStr)
100 | }
101 | if port < 1 || port > 0xffff {
102 | return nil, errors.New("socks: port number out of range: " + portStr)
103 | }
104 |
105 | buff := make([]byte, 0, 6+len(host))
106 |
107 | buff = append(buff, socks5Version)
108 |
109 | // set authentication methods
110 | if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
111 | buff = append(buff, 2, socks5AuthNone, socks5AuthPassword)
112 | } else {
113 | buff = append(buff, 1, socks5AuthNone)
114 | }
115 |
116 | // send authentication methods
117 | if _, err := conn.Write(buff); err != nil {
118 | return nil, errors.New("socks: failed to write handshake request at: " + s.address + ": " + err.Error())
119 | }
120 | if _, err := io.ReadFull(conn, buff[:2]); err != nil {
121 | return nil, errors.New("socks: failed to read handshake reply at: " + s.address + ": " + err.Error())
122 | }
123 |
124 | // handle authentication methods reply
125 | if buff[0] != socks5Version {
126 | return nil, errors.New("socks: SOCKS5 server at: " + s.address + " invalid version" + strconv.Itoa(int(buff[0])))
127 | }
128 | if buff[1] == socks5AuthNoAccept {
129 | return nil, errors.New("socks: SOCKS server at: " + s.address + " no acceptable methods")
130 | }
131 |
132 | if buff[1] == socks5AuthPassword {
133 | // build username/password authentication request
134 | buff = buff[:0]
135 | buff = append(buff, socks5AuthPasswordVer)
136 | buff = append(buff, uint8(len(s.user)))
137 | buff = append(buff, []byte(s.user)...)
138 | buff = append(buff, uint8(len(s.password)))
139 | buff = append(buff, []byte(s.password)...)
140 |
141 | if _, err := conn.Write(buff); err != nil {
142 | return nil, errors.New("socks: failed to write password authentication request to SOCKS5 server at: " + s.address + ": " + err.Error())
143 | }
144 | if _, err := io.ReadFull(conn, buff[:2]); err != nil {
145 | return nil, errors.New("socks: failed to read password authentication reply from SOCKS5 server at: " + s.address + ": " + err.Error())
146 | }
147 | // 0 indicates success
148 | if buff[1] != 0 {
149 | return nil, errors.New("socks: SOCKS5 server at: " + s.address + " reject username/password")
150 | }
151 | }
152 |
153 | // build connect request
154 | buff = buff[:0]
155 | buff = append(buff, socks5Version, socks5Connect, 0)
156 |
157 | if ip := net.ParseIP(host); ip != nil {
158 | if ip4 := ip.To4(); ip4 != nil {
159 | buff = append(buff, socks5IP4)
160 | ip = ip4
161 | } else {
162 | buff = append(buff, socks5IP6)
163 | }
164 | buff = append(buff, ip...)
165 | } else {
166 | if len(host) > 255 {
167 | return nil, errors.New("socks: destination hostname too long: " + host)
168 | }
169 | buff = append(buff, socks5Domain)
170 | buff = append(buff, uint8(len(host)))
171 | buff = append(buff, host...)
172 | }
173 | buff = append(buff, byte(port>>8), byte(port))
174 |
175 | if _, err := conn.Write(buff); err != nil {
176 | return nil, errors.New("socks: failed to write connect request to SOCKS5 server at: " + s.address + ": " + err.Error())
177 | }
178 | if _, err := io.ReadFull(conn, buff[:4]); err != nil {
179 | return nil, errors.New("socks: failed to read connect reply from SOCKS5 server at: " + s.address + ": " + err.Error())
180 | }
181 |
182 | failure := "unknown error"
183 | if int(buff[1]) < len(socks5Errors) {
184 | failure = socks5Errors[buff[1]]
185 | }
186 | if len(failure) > 0 {
187 | return nil, errors.New("socks: SOCKS5 server failed to connect: " + failure)
188 | }
189 |
190 | // read remain data include BIND.ADDRESS and BIND.PORT
191 | discardBytes := 0
192 | switch buff[3] {
193 | case socks5IP4:
194 | discardBytes = net.IPv4len
195 | case socks5IP6:
196 | discardBytes = net.IPv6len
197 | case socks5Domain:
198 | if _, err := io.ReadFull(conn, buff[:1]); err != nil {
199 | return nil, errors.New("socks: failed to read domain length from SOCKS5 server at: " + s.address + ": " + err.Error())
200 | }
201 | discardBytes = int(buff[0])
202 | default:
203 | return nil, errors.New("socks: got unknown address type " + strconv.Itoa(int(buff[3])) + " from SOCKS5 server at: " + s.address)
204 | }
205 | discardBytes += 2
206 | if cap(buff) < discardBytes {
207 | buff = make([]byte, discardBytes)
208 | } else {
209 | buff = buff[:discardBytes]
210 | }
211 | if _, err := io.ReadFull(conn, buff); err != nil {
212 | return nil, errors.New("socks: failed to read address and port from SOCKS5 server at: " + s.address + ": " + err.Error())
213 | }
214 |
215 | closeConn = nil
216 | return conn, nil
217 | }
218 |
219 | func serveSocks5Client(conn net.Conn, forward Dialer) {
220 | defer conn.Close()
221 |
222 | buff := make([]byte, 262)
223 | reply := []byte{0x05, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22}
224 |
225 | if _, err := io.ReadFull(conn, buff[:2]); err != nil {
226 | return
227 | }
228 | if buff[0] != socks5Version {
229 | reply[1] = socks5AuthNoAccept
230 | conn.Write(reply[:2])
231 | return
232 | }
233 | numMethod := buff[1]
234 | if _, err := io.ReadFull(conn, buff[:numMethod]); err != nil {
235 | return
236 | }
237 | reply[1] = socks5AuthNone
238 | if _, err := conn.Write(reply[:2]); err != nil {
239 | return
240 | }
241 |
242 | if _, err := io.ReadFull(conn, buff[:4]); err != nil {
243 | return
244 | }
245 | if buff[1] != socks5Connect {
246 | reply[1] = socks5CommandNotSupported
247 | conn.Write(reply)
248 | return
249 | }
250 |
251 | addressType := buff[3]
252 | addressLen := 0
253 | switch addressType {
254 | case socks5IP4:
255 | addressLen = net.IPv4len
256 | case socks5IP6:
257 | addressLen = net.IPv6len
258 | case socks5Domain:
259 | if _, err := io.ReadFull(conn, buff[:1]); err != nil {
260 | return
261 | }
262 | addressLen = int(buff[0])
263 | default:
264 | reply[1] = socks5AddressTypeNotSupported
265 | conn.Write(reply)
266 | return
267 | }
268 | host := make([]byte, addressLen)
269 | if _, err := io.ReadFull(conn, host); err != nil {
270 | return
271 | }
272 | if _, err := io.ReadFull(conn, buff[:2]); err != nil {
273 | return
274 | }
275 | hostStr := ""
276 | switch addressType {
277 | case socks5IP4, socks5IP6:
278 | ip := net.IP(host)
279 | hostStr = ip.String()
280 | case socks5Domain:
281 | hostStr = string(host)
282 | }
283 | port := uint16(buff[0])<<8 | uint16(buff[1])
284 | if port < 1 || port > 0xffff {
285 | reply[1] = socks5HostUnreachable
286 | conn.Write(reply)
287 | return
288 | }
289 | portStr := strconv.Itoa(int(port))
290 |
291 | hostStr = net.JoinHostPort(hostStr, portStr)
292 | dest, err := forward.Dial("tcp", hostStr)
293 | if err != nil {
294 | reply[1] = socks5ConnectionRefused
295 | conn.Write(reply)
296 | return
297 | }
298 | defer dest.Close()
299 | reply[1] = socks5Success
300 | if _, err := conn.Write(reply); err != nil {
301 | return
302 | }
303 |
304 | go func() {
305 | defer conn.Close()
306 | defer dest.Close()
307 | io.Copy(conn, dest)
308 | }()
309 |
310 | io.Copy(dest, conn)
311 | }
312 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/socks5_client_test.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import (
4 | "net"
5 | "net/http"
6 | "net/http/httputil"
7 | "testing"
8 | )
9 |
10 | const (
11 | TestSocks5ServerAddress = "127.0.0.1:8001"
12 | TestSocks5TargetDomain = "www.baidu.com"
13 | )
14 |
15 | func TestSocks5Client(t *testing.T) {
16 | listener, err := net.Listen("tcp", TestSocks5ServerAddress)
17 | if err != nil {
18 | t.Fatal(err)
19 | }
20 | defer listener.Close()
21 |
22 | go func() {
23 | server, err := NewSocks5Server(Direct)
24 | if err != nil {
25 | t.Fatal(err)
26 | }
27 | server.Serve(listener)
28 | }()
29 |
30 | client, err := NewSocks5Client("tcp", TestSocks5ServerAddress, "", "", Direct)
31 | if err != nil {
32 | t.Fatal(err)
33 | }
34 | conn, err := client.Dial("tcp", TestSocks5TargetDomain+":80")
35 | if err != nil {
36 | t.Fatal(err)
37 | }
38 |
39 | t.Log("client.Dial succeeded")
40 | httpClient := httputil.NewClientConn(conn, nil)
41 | if err != nil {
42 | conn.Close()
43 | t.Fatal(err)
44 | }
45 | defer httpClient.Close()
46 |
47 | request, err := http.NewRequest("GET", "/", nil)
48 | if err != nil {
49 | t.Fatal(err)
50 | }
51 | resp, err := httpClient.Do(request)
52 | if err != nil {
53 | t.Fatal(err)
54 | }
55 | data, err := httputil.DumpResponse(resp, true)
56 | if err != nil {
57 | t.Fatal(err)
58 | }
59 | t.Log("socks5 HTTP Get:", string(data))
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/vendor/github.com/eahydra/socks/socks5_server.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import "net"
4 |
5 | // Socks5Server implements Socks5 Proxy Protocol(RFC 1928), just support CONNECT command.
6 | type Socks5Server struct {
7 | forward Dialer
8 | }
9 |
10 | // NewSocks5Server return a new Socks5Server
11 | func NewSocks5Server(forward Dialer) (*Socks5Server, error) {
12 | return &Socks5Server{
13 | forward: forward,
14 | }, nil
15 | }
16 |
17 | // Serve with net.Listener for new incoming clients.
18 | func (s *Socks5Server) Serve(listener net.Listener) error {
19 | for {
20 | conn, err := listener.Accept()
21 | if err != nil {
22 | if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
23 | continue
24 | } else {
25 | return err
26 | }
27 | }
28 |
29 | go serveSocks5Client(conn, s.forward)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Elazar Leibovich. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Elazar Leibovich. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | [](https://godoc.org/github.com/elazarl/goproxy)
4 | [](https://gitter.im/elazarl/goproxy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5 |
6 | Package goproxy provides a customizable HTTP proxy library for Go (golang),
7 |
8 | It supports regular HTTP proxy, HTTPS through CONNECT, and "hijacking" HTTPS
9 | connection using "Man in the Middle" style attack.
10 |
11 | The intent of the proxy, is to be usable with reasonable amount of traffic
12 | yet, customizable and programable.
13 |
14 | The proxy itself is simply a `net/http` handler.
15 |
16 | In order to use goproxy, one should set their browser to use goproxy as an HTTP
17 | proxy. Here is how you do that [in Chrome](https://support.google.com/chrome/answer/96815?hl=en)
18 | and [in Firefox](http://www.wikihow.com/Enter-Proxy-Settings-in-Firefox).
19 |
20 | For example, the URL you should use as proxy when running `./bin/basic` is
21 | `localhost:8080`, as this is the default binding for the basic proxy.
22 |
23 | ## Mailing List
24 |
25 | New features would be discussed on the [mailing list](https://groups.google.com/forum/#!forum/goproxy-dev)
26 | before their development.
27 |
28 | ## Latest Stable Release
29 |
30 | Get the latest goproxy from `gopkg.in/elazarl/goproxy.v1`.
31 |
32 | # Why not Fiddler2?
33 |
34 | Fiddler is an excellent software with similar intent. However, Fiddler is not
35 | as customable as goproxy intend to be. The main difference is, Fiddler is not
36 | intended to be used as a real proxy.
37 |
38 | A possible use case that suits goproxy but
39 | not Fiddler, is, gathering statistics on page load times for a certain website over a week.
40 | With goproxy you could ask all your users to set their proxy to a dedicated machine running a
41 | goproxy server. Fiddler is a GUI app not designed to be ran like a server for multiple users.
42 |
43 | # A taste of goproxy
44 |
45 | To get a taste of `goproxy`, a basic HTTP/HTTPS transparent proxy
46 |
47 |
48 | package main
49 |
50 | import (
51 | "github.com/elazarl/goproxy"
52 | "log"
53 | "net/http"
54 | )
55 |
56 | func main() {
57 | proxy := goproxy.NewProxyHttpServer()
58 | proxy.Verbose = true
59 | log.Fatal(http.ListenAndServe(":8080", proxy))
60 | }
61 |
62 |
63 | This line will add `X-GoProxy: yxorPoG-X` header to all requests sent through the proxy
64 |
65 | proxy.OnRequest().DoFunc(
66 | func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
67 | r.Header.Set("X-GoProxy","yxorPoG-X")
68 | return r,nil
69 | })
70 |
71 | `DoFunc` will process all incoming requests to the proxy. It will add a header to the request
72 | and return it. The proxy will send the modified request.
73 |
74 | Note that we returned nil value as the response. Have we returned a response, goproxy would
75 | have discarded the request and sent the new response to the client.
76 |
77 | In order to refuse connections to reddit at work time
78 |
79 | proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
80 | func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
81 | if h,_,_ := time.Now().Clock(); h >= 8 && h <= 17 {
82 | return r,goproxy.NewResponse(r,
83 | goproxy.ContentTypeText,http.StatusForbidden,
84 | "Don't waste your time!")
85 | }
86 | return r,nil
87 | })
88 |
89 | `DstHostIs` returns a `ReqCondition`, that is a function receiving a `Request` and returning a boolean
90 | we will only process requests that matches the condition. `DstHostIs("www.reddit.com")` will return
91 | a `ReqCondition` accepting only requests directed to "www.reddit.com".
92 |
93 | `DoFunc` will recieve a function that will preprocess the request. We can change the request, or
94 | return a response. If the time is between 8:00am and 17:00pm, we will neglect the request, and
95 | return a precanned text response saying "do not waste your time".
96 |
97 | See additional examples in the examples directory.
98 |
99 | # What's New
100 |
101 | 1. Ability to `Hijack` CONNECT requests. See
102 | [the eavesdropper example](https://github.com/elazarl/goproxy/blob/master/examples/goproxy-eavesdropper/main.go#L27)
103 | 2. Transparent proxy support for http/https including MITM certificate generation for TLS. See the [transparent example.](https://github.com/elazarl/goproxy/tree/master/examples/goproxy-transparent)
104 |
105 | # License
106 |
107 | I put the software temporarily under the Go-compatible BSD license,
108 | if this prevents someone from using the software, do let mee know and I'll consider changing it.
109 |
110 | At any rate, user feedback is very important for me, so I'll be delighted to know if you're using this package.
111 |
112 | # Beta Software
113 |
114 | I've received a positive feedback from a few people who use goproxy in production settings.
115 | I believe it is good enough for usage.
116 |
117 | I'll try to keep reasonable backwards compatability. In case of a major API change,
118 | I'll change the import path.
119 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/actions.go:
--------------------------------------------------------------------------------
1 | package goproxy
2 |
3 | import "net/http"
4 |
5 | // ReqHandler will "tamper" with the request coming to the proxy server
6 | // If Handle returns req,nil the proxy will send the returned request
7 | // to the destination server. If it returns nil,resp the proxy will
8 | // skip sending any requests, and will simply return the response `resp`
9 | // to the client.
10 | type ReqHandler interface {
11 | Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response)
12 | }
13 |
14 | // A wrapper that would convert a function to a ReqHandler interface type
15 | type FuncReqHandler func(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response)
16 |
17 | // FuncReqHandler.Handle(req,ctx) <=> FuncReqHandler(req,ctx)
18 | func (f FuncReqHandler) Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) {
19 | return f(req, ctx)
20 | }
21 |
22 | // after the proxy have sent the request to the destination server, it will
23 | // "filter" the response through the RespHandlers it has.
24 | // The proxy server will send to the client the response returned by the RespHandler.
25 | // In case of error, resp will be nil, and ctx.RoundTrip.Error will contain the error
26 | type RespHandler interface {
27 | Handle(resp *http.Response, ctx *ProxyCtx) *http.Response
28 | }
29 |
30 | // A wrapper that would convert a function to a RespHandler interface type
31 | type FuncRespHandler func(resp *http.Response, ctx *ProxyCtx) *http.Response
32 |
33 | // FuncRespHandler.Handle(req,ctx) <=> FuncRespHandler(req,ctx)
34 | func (f FuncRespHandler) Handle(resp *http.Response, ctx *ProxyCtx) *http.Response {
35 | return f(resp, ctx)
36 | }
37 |
38 | // When a client send a CONNECT request to a host, the request is filtered through
39 | // all the HttpsHandlers the proxy has, and if one returns true, the connection is
40 | // sniffed using Man in the Middle attack.
41 | // That is, the proxy will create a TLS connection with the client, another TLS
42 | // connection with the destination the client wished to connect to, and would
43 | // send back and forth all messages from the server to the client and vice versa.
44 | // The request and responses sent in this Man In the Middle channel are filtered
45 | // through the usual flow (request and response filtered through the ReqHandlers
46 | // and RespHandlers)
47 | type HttpsHandler interface {
48 | HandleConnect(req string, ctx *ProxyCtx) (*ConnectAction, string)
49 | }
50 |
51 | // A wrapper that would convert a function to a HttpsHandler interface type
52 | type FuncHttpsHandler func(host string, ctx *ProxyCtx) (*ConnectAction, string)
53 |
54 | // FuncHttpsHandler should implement the RespHandler interface
55 | func (f FuncHttpsHandler) HandleConnect(host string, ctx *ProxyCtx) (*ConnectAction, string) {
56 | return f(host, ctx)
57 | }
58 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/all.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | go test || exit
4 | for action in $@; do go $action; done
5 |
6 | mkdir -p bin
7 | find regretable examples/* ext/* -maxdepth 0 -type d | while read d; do
8 | (cd $d
9 | go build -o ../../bin/$(basename $d)
10 | find *_test.go -maxdepth 0 2>/dev/null|while read f;do
11 | for action in $@; do go $action; done
12 | go test
13 | break
14 | done)
15 | done
16 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICSjCCAbWgAwIBAgIBADALBgkqhkiG9w0BAQUwSjEjMCEGA1UEChMaZ2l0aHVi
3 | LmNvbS9lbGF6YXJsL2dvcHJveHkxIzAhBgNVBAMTGmdpdGh1Yi5jb20vZWxhemFy
4 | bC9nb3Byb3h5MB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowSjEjMCEG
5 | A1UEChMaZ2l0aHViLmNvbS9lbGF6YXJsL2dvcHJveHkxIzAhBgNVBAMTGmdpdGh1
6 | Yi5jb20vZWxhemFybC9nb3Byb3h5MIGdMAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEA
7 | vz9BbCaJjxs73Tvcq3leP32hAGerQ1RgvlZ68Z4nZmoVHfl+2Nr/m0dmW+GdOfpT
8 | cs/KzfJjYGr/84x524fiuR8GdZ0HOtXJzyF5seoWnbBIuyr1PbEpgRhGQMqqOUuj
9 | YExeLbfNHPIoJ8XZ1Vzyv3YxjbmjWA+S/uOe9HWtDbMCAwEAAaNGMEQwDgYDVR0P
10 | AQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8w
11 | DAYDVR0RBAUwA4IBKjALBgkqhkiG9w0BAQUDgYEAIcL8huSmGMompNujsvePTUnM
12 | oEUKtX4Eh/+s+DSfV/TyI0I+3GiPpLplEgFWuoBIJGios0r1dKh5N0TGjxX/RmGm
13 | qo7E4jjJuo8Gs5U8/fgThZmshax2lwLtbRNwhvUVr65GdahLsZz8I+hySLuatVvR
14 | qHHq/FQORIiNyNpq/Hg=
15 | -----END CERTIFICATE-----
16 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/certs.go:
--------------------------------------------------------------------------------
1 | package goproxy
2 |
3 | import (
4 | "crypto/tls"
5 | "crypto/x509"
6 | )
7 |
8 | func init() {
9 | if goproxyCaErr != nil {
10 | panic("Error parsing builtin CA " + goproxyCaErr.Error())
11 | }
12 | var err error
13 | if GoproxyCa.Leaf, err = x509.ParseCertificate(GoproxyCa.Certificate[0]); err != nil {
14 | panic("Error parsing builtin CA " + err.Error())
15 | }
16 | }
17 |
18 | var tlsClientSkipVerify = &tls.Config{InsecureSkipVerify: true}
19 |
20 | var defaultTLSConfig = &tls.Config{
21 | InsecureSkipVerify: true,
22 | }
23 |
24 | var CA_CERT = []byte(`-----BEGIN CERTIFICATE-----
25 | MIIF9DCCA9ygAwIBAgIJAODqYUwoVjJkMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYD
26 | VQQGEwJJTDEPMA0GA1UECAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoM
27 | B0dvUHJveHkxEDAOBgNVBAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0
28 | aHViLmlvMSAwHgYJKoZIhvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTAeFw0xNzA0
29 | MDUyMDAwMTBaFw0zNzAzMzEyMDAwMTBaMIGOMQswCQYDVQQGEwJJTDEPMA0GA1UE
30 | CAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoMB0dvUHJveHkxEDAOBgNV
31 | BAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0aHViLmlvMSAwHgYJKoZI
32 | hvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
33 | ADCCAgoCggIBAJ4Qy+H6hhoY1s0QRcvIhxrjSHaO/RbaFj3rwqcnpOgFq07gRdI9
34 | 3c0TFKQJHpgv6feLRhEvX/YllFYu4J35lM9ZcYY4qlKFuStcX8Jm8fqpgtmAMBzP
35 | sqtqDi8M9RQGKENzU9IFOnCV7SAeh45scMuI3wz8wrjBcH7zquHkvqUSYZz035t9
36 | V6WTrHyTEvT4w+lFOVN2bA/6DAIxrjBiF6DhoJqnha0SZtDfv77XpwGG3EhA/qoh
37 | hiYrDruYK7zJdESQL44LwzMPupVigqalfv+YHfQjbhT951IVurW2NJgRyBE62dLr
38 | lHYdtT9tCTCrd+KJNMJ+jp9hAjdIu1Br/kifU4F4+4ZLMR9Ueji0GkkPKsYdyMnq
39 | j0p0PogyvP1l4qmboPImMYtaoFuYmMYlebgC9LN10bL91K4+jLt0I1YntEzrqgJo
40 | WsJztYDw543NzSy5W+/cq4XRYgtq1b0RWwuUiswezmMoeyHZ8BQJe2xMjAOllASD
41 | fqa8OK3WABHJpy4zUrnUBiMuPITzD/FuDx4C5IwwlC68gHAZblNqpBZCX0nFCtKj
42 | YOcI2So5HbQ2OC8QF+zGVuduHUSok4hSy2BBfZ1pfvziqBeetWJwFvapGB44nIHh
43 | WKNKvqOxLNIy7e+TGRiWOomrAWM18VSR9LZbBxpJK7PLSzWqYJYTRCZHAgMBAAGj
44 | UzBRMB0GA1UdDgQWBBR4uDD9Y6x7iUoHO+32ioOcw1ICZTAfBgNVHSMEGDAWgBR4
45 | uDD9Y6x7iUoHO+32ioOcw1ICZTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
46 | CwUAA4ICAQAaCEupzGGqcdh+L7BzhX7zyd7yzAKUoLxFrxaZY34Xyj3lcx1XoK6F
47 | AqsH2JM25GixgadzhNt92JP7vzoWeHZtLfstrPS638Y1zZi6toy4E49viYjFk5J0
48 | C6ZcFC04VYWWx6z0HwJuAS08tZ37JuFXpJGfXJOjZCQyxse0Lg0tuKLMeXDCk2Y3
49 | Ba0noeuNyHRoWXXPyiUoeApkVCU5gIsyiJSWOjhJ5hpJG06rQNfNYexgKrrraEin
50 | o0jmEMtJMx5TtD83hSnLCnFGBBq5lkE7jgXME1KsbIE3lJZzRX1mQwUK8CJDYxye
51 | i6M/dzSvy0SsPvz8fTAlprXRtWWtJQmxgWENp3Dv+0Pmux/l+ilk7KA4sMXGhsfr
52 | bvTOeWl1/uoFTPYiWR/ww7QEPLq23yDFY04Q7Un0qjIk8ExvaY8lCkXMgc8i7sGY
53 | VfvOYb0zm67EfAQl3TW8Ky5fl5CcxpVCD360Bzi6hwjYixa3qEeBggOixFQBFWft
54 | 8wrkKTHpOQXjn4sDPtet8imm9UYEtzWrFX6T9MFYkBR0/yye0FIh9+YPiTA6WB86
55 | NCNwK5Yl6HuvF97CIH5CdgO+5C7KifUtqTOL8pQKbNwy0S3sNYvB+njGvRpR7pKV
56 | BUnFpB/Atptqr4CUlTXrc5IPLAqAfmwk5IKcwy3EXUbruf9Dwz69YA==
57 | -----END CERTIFICATE-----`)
58 |
59 | var CA_KEY = []byte(`-----BEGIN RSA PRIVATE KEY-----
60 | MIIJKAIBAAKCAgEAnhDL4fqGGhjWzRBFy8iHGuNIdo79FtoWPevCpyek6AWrTuBF
61 | 0j3dzRMUpAkemC/p94tGES9f9iWUVi7gnfmUz1lxhjiqUoW5K1xfwmbx+qmC2YAw
62 | HM+yq2oOLwz1FAYoQ3NT0gU6cJXtIB6Hjmxwy4jfDPzCuMFwfvOq4eS+pRJhnPTf
63 | m31XpZOsfJMS9PjD6UU5U3ZsD/oMAjGuMGIXoOGgmqeFrRJm0N+/vtenAYbcSED+
64 | qiGGJisOu5grvMl0RJAvjgvDMw+6lWKCpqV+/5gd9CNuFP3nUhW6tbY0mBHIETrZ
65 | 0uuUdh21P20JMKt34ok0wn6On2ECN0i7UGv+SJ9TgXj7hksxH1R6OLQaSQ8qxh3I
66 | yeqPSnQ+iDK8/WXiqZug8iYxi1qgW5iYxiV5uAL0s3XRsv3Urj6Mu3QjVie0TOuq
67 | AmhawnO1gPDnjc3NLLlb79yrhdFiC2rVvRFbC5SKzB7OYyh7IdnwFAl7bEyMA6WU
68 | BIN+prw4rdYAEcmnLjNSudQGIy48hPMP8W4PHgLkjDCULryAcBluU2qkFkJfScUK
69 | 0qNg5wjZKjkdtDY4LxAX7MZW524dRKiTiFLLYEF9nWl+/OKoF561YnAW9qkYHjic
70 | geFYo0q+o7Es0jLt75MZGJY6iasBYzXxVJH0tlsHGkkrs8tLNapglhNEJkcCAwEA
71 | AQKCAgAwSuNvxHHqUUJ3XoxkiXy1u1EtX9x1eeYnvvs2xMb+WJURQTYz2NEGUdkR
72 | kPO2/ZSXHAcpQvcnpi2e8y2PNmy/uQ0VPATVt6NuWweqxncR5W5j82U/uDlXY8y3
73 | lVbfak4s5XRri0tikHvlP06dNgZ0OPok5qi7d+Zd8yZ3Y8LXfjkykiIrSG1Z2jdt
74 | zCWTkNmSUKMGG/1CGFxI41Lb12xuq+C8v4f469Fb6bCUpyCQN9rffHQSGLH6wVb7
75 | +68JO+d49zCATpmx5RFViMZwEcouXxRvvc9pPHXLP3ZPBD8nYu9kTD220mEGgWcZ
76 | 3L9dDlZPcSocbjw295WMvHz2QjhrDrb8gXwdpoRyuyofqgCyNxSnEC5M13SjOxtf
77 | pjGzjTqh0kDlKXg2/eTkd9xIHjVhFYiHIEeITM/lHCfWwBCYxViuuF7pSRPzTe8U
78 | C440b62qZSPMjVoquaMg+qx0n9fKSo6n1FIKHypv3Kue2G0WhDeK6u0U288vQ1t4
79 | Ood3Qa13gZ+9hwDLbM/AoBfVBDlP/tpAwa7AIIU1ZRDNbZr7emFdctx9B6kLINv3
80 | 4PDOGM2xrjOuACSGMq8Zcu7LBz35PpIZtviJOeKNwUd8/xHjWC6W0itgfJb5I1Nm
81 | V6Vj368pGlJx6Se26lvXwyyrc9pSw6jSAwARBeU4YkNWpi4i6QKCAQEA0T7u3P/9
82 | jZJSnDN1o2PXymDrJulE61yguhc/QSmLccEPZe7or06/DmEhhKuCbv+1MswKDeag
83 | /1JdFPGhL2+4G/f/9BK3BJPdcOZSz7K6Ty8AMMBf8AehKTcSBqwkJWcbEvpHpKJ6
84 | eDqn1B6brXTNKMT6fEEXCuZJGPBpNidyLv/xXDcN7kCOo3nGYKfB5OhFpNiL63tw
85 | +LntU56WESZwEqr8Pf80uFvsyXQK3a5q5HhIQtxl6tqQuPlNjsDBvCqj0x72mmaJ
86 | ZVsVWlv7khUrCwAXz7Y8K7mKKBd2ekF5hSbryfJsxFyvEaWUPhnJpTKV85lAS+tt
87 | FQuIp9TvKYlRQwKCAQEAwWJN8jysapdhi67jO0HtYOEl9wwnF4w6XtiOYtllkMmC
88 | 06/e9h7RsRyWPMdu3qRDPUYFaVDy6+dpUDSQ0+E2Ot6AHtVyvjeUTIL651mFIo/7
89 | OSUCEc+HRo3SfPXdPhSQ2thNTxl6y9XcFacuvbthgr70KXbvC4k6IEmdpf/0Kgs9
90 | 7QTZCG26HDrEZ2q9yMRlRaL2SRD+7Y2xra7gB+cQGFj6yn0Wd/07er49RqMXidQf
91 | KR2oYfev2BDtHXoSZFfhFGHlOdLvWRh90D4qZf4vQ+g/EIMgcNSoxjvph1EShmKt
92 | sjhTHtoHuu+XmEQvIewk2oCI+JvofBkcnpFrVvUUrQKCAQAaTIufETmgCo0BfuJB
93 | N/JOSGIl0NnNryWwXe2gVgVltbsmt6FdL0uKFiEtWJUbOF5g1Q5Kcvs3O/XhBQGa
94 | QbNlKIVt+tAv7hm97+Tmn/MUsraWagdk1sCluns0hXxBizT27KgGhDlaVRz05yfv
95 | 5CdJAYDuDwxDXXBAhy7iFJEgYSDH00+X61tCJrMNQOh4ycy/DEyBu1EWod+3S85W
96 | t3sMjZsIe8P3i+4137Th6eMbdha2+JaCrxfTd9oMoCN5b+6JQXIDM/H+4DTN15PF
97 | 540yY7+aZrAnWrmHknNcqFAKsTqfdi2/fFqwoBwCtiEG91WreU6AfEWIiJuTZIru
98 | sIibAoIBAAqIwlo5t+KukF+9jR9DPh0S5rCIdvCvcNaN0WPNF91FPN0vLWQW1bFi
99 | L0TsUDvMkuUZlV3hTPpQxsnZszH3iK64RB5p3jBCcs+gKu7DT59MXJEGVRCHT4Um
100 | YJryAbVKBYIGWl++sZO8+JotWzx2op8uq7o+glMMjKAJoo7SXIiVyC/LHc95urOi
101 | 9+PySphPKn0anXPpexmRqGYfqpCDo7rPzgmNutWac80B4/CfHb8iUPg6Z1u+1FNe
102 | yKvcZHgW2Wn00znNJcCitufLGyAnMofudND/c5rx2qfBx7zZS7sKUQ/uRYjes6EZ
103 | QBbJUA/2/yLv8YYpaAaqj4aLwV8hRpkCggEBAIh3e25tr3avCdGgtCxS7Y1blQ2c
104 | ue4erZKmFP1u8wTNHQ03T6sECZbnIfEywRD/esHpclfF3kYAKDRqIP4K905Rb0iH
105 | 759ZWt2iCbqZznf50XTvptdmjm5KxvouJzScnQ52gIV6L+QrCKIPelLBEIqCJREh
106 | pmcjjocD/UCCSuHgbAYNNnO/JdhnSylz1tIg26I+2iLNyeTKIepSNlsBxnkLmqM1
107 | cj/azKBaT04IOMLaN8xfSqitJYSraWMVNgGJM5vfcVaivZnNh0lZBv+qu6YkdM88
108 | 4/avCJ8IutT+FcMM+GbGazOm5ALWqUyhrnbLGc4CQMPfe7Il6NxwcrOxT8w=
109 | -----END RSA PRIVATE KEY-----`)
110 |
111 | var GoproxyCa, goproxyCaErr = tls.X509KeyPair(CA_CERT, CA_KEY)
112 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/chunked.go:
--------------------------------------------------------------------------------
1 | // Taken from $GOROOT/src/pkg/net/http/chunked
2 | // needed to write https responses to client.
3 | package goproxy
4 |
5 | import (
6 | "io"
7 | "strconv"
8 | )
9 |
10 | // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
11 | // "chunked" format before writing them to w. Closing the returned chunkedWriter
12 | // sends the final 0-length chunk that marks the end of the stream.
13 | //
14 | // newChunkedWriter is not needed by normal applications. The http
15 | // package adds chunking automatically if handlers don't set a
16 | // Content-Length header. Using newChunkedWriter inside a handler
17 | // would result in double chunking or chunking with a Content-Length
18 | // length, both of which are wrong.
19 | func newChunkedWriter(w io.Writer) io.WriteCloser {
20 | return &chunkedWriter{w}
21 | }
22 |
23 | // Writing to chunkedWriter translates to writing in HTTP chunked Transfer
24 | // Encoding wire format to the underlying Wire chunkedWriter.
25 | type chunkedWriter struct {
26 | Wire io.Writer
27 | }
28 |
29 | // Write the contents of data as one chunk to Wire.
30 | // NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
31 | // a bug since it does not check for success of io.WriteString
32 | func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
33 |
34 | // Don't send 0-length data. It looks like EOF for chunked encoding.
35 | if len(data) == 0 {
36 | return 0, nil
37 | }
38 |
39 | head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
40 |
41 | if _, err = io.WriteString(cw.Wire, head); err != nil {
42 | return 0, err
43 | }
44 | if n, err = cw.Wire.Write(data); err != nil {
45 | return
46 | }
47 | if n != len(data) {
48 | err = io.ErrShortWrite
49 | return
50 | }
51 | _, err = io.WriteString(cw.Wire, "\r\n")
52 |
53 | return
54 | }
55 |
56 | func (cw *chunkedWriter) Close() error {
57 | _, err := io.WriteString(cw.Wire, "0\r\n")
58 | return err
59 | }
60 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/counterecryptor.go:
--------------------------------------------------------------------------------
1 | package goproxy
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/cipher"
6 | "crypto/rsa"
7 | "crypto/sha256"
8 | "crypto/x509"
9 | "errors"
10 | )
11 |
12 | type CounterEncryptorRand struct {
13 | cipher cipher.Block
14 | counter []byte
15 | rand []byte
16 | ix int
17 | }
18 |
19 | func NewCounterEncryptorRandFromKey(key interface{}, seed []byte) (r CounterEncryptorRand, err error) {
20 | var keyBytes []byte
21 | switch key := key.(type) {
22 | case *rsa.PrivateKey:
23 | keyBytes = x509.MarshalPKCS1PrivateKey(key)
24 | default:
25 | err = errors.New("only RSA keys supported")
26 | return
27 | }
28 | h := sha256.New()
29 | if r.cipher, err = aes.NewCipher(h.Sum(keyBytes)[:aes.BlockSize]); err != nil {
30 | return
31 | }
32 | r.counter = make([]byte, r.cipher.BlockSize())
33 | if seed != nil {
34 | copy(r.counter, h.Sum(seed)[:r.cipher.BlockSize()])
35 | }
36 | r.rand = make([]byte, r.cipher.BlockSize())
37 | r.ix = len(r.rand)
38 | return
39 | }
40 |
41 | func (c *CounterEncryptorRand) Seed(b []byte) {
42 | if len(b) != len(c.counter) {
43 | panic("SetCounter: wrong counter size")
44 | }
45 | copy(c.counter, b)
46 | }
47 |
48 | func (c *CounterEncryptorRand) refill() {
49 | c.cipher.Encrypt(c.rand, c.counter)
50 | for i := 0; i < len(c.counter); i++ {
51 | if c.counter[i]++; c.counter[i] != 0 {
52 | break
53 | }
54 | }
55 | c.ix = 0
56 | }
57 |
58 | func (c *CounterEncryptorRand) Read(b []byte) (n int, err error) {
59 | if c.ix == len(c.rand) {
60 | c.refill()
61 | }
62 | if n = len(c.rand) - c.ix; n > len(b) {
63 | n = len(b)
64 | }
65 | copy(b, c.rand[c.ix:c.ix+n])
66 | c.ix += n
67 | return
68 | }
69 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/counterecryptor_test.go:
--------------------------------------------------------------------------------
1 | package goproxy_test
2 |
3 | import (
4 | "bytes"
5 | "crypto/rsa"
6 | "encoding/binary"
7 | "github.com/elazarl/goproxy"
8 | "io"
9 | "math"
10 | "math/rand"
11 | "testing"
12 | )
13 |
14 | type RandSeedReader struct {
15 | r rand.Rand
16 | }
17 |
18 | func (r *RandSeedReader) Read(b []byte) (n int, err error) {
19 | for i := range b {
20 | b[i] = byte(r.r.Int() & 0xFF)
21 | }
22 | return len(b), nil
23 | }
24 |
25 | func TestCounterEncDifferentConsecutive(t *testing.T) {
26 | k, err := rsa.GenerateKey(&RandSeedReader{*rand.New(rand.NewSource(0xFF43109))}, 128)
27 | fatalOnErr(err, "rsa.GenerateKey", t)
28 | c, err := goproxy.NewCounterEncryptorRandFromKey(k, []byte("the quick brown fox run over the lazy dog"))
29 | fatalOnErr(err, "NewCounterEncryptorRandFromKey", t)
30 | for i := 0; i < 100*1000; i++ {
31 | var a, b int64
32 | binary.Read(&c, binary.BigEndian, &a)
33 | binary.Read(&c, binary.BigEndian, &b)
34 | if a == b {
35 | t.Fatal("two consecutive equal int64", a, b)
36 | }
37 | }
38 | }
39 |
40 | func TestCounterEncIdenticalStreams(t *testing.T) {
41 | k, err := rsa.GenerateKey(&RandSeedReader{*rand.New(rand.NewSource(0xFF43109))}, 128)
42 | fatalOnErr(err, "rsa.GenerateKey", t)
43 | c1, err := goproxy.NewCounterEncryptorRandFromKey(k, []byte("the quick brown fox run over the lazy dog"))
44 | fatalOnErr(err, "NewCounterEncryptorRandFromKey", t)
45 | c2, err := goproxy.NewCounterEncryptorRandFromKey(k, []byte("the quick brown fox run over the lazy dog"))
46 | fatalOnErr(err, "NewCounterEncryptorRandFromKey", t)
47 | nout := 1000
48 | out1, out2 := make([]byte, nout), make([]byte, nout)
49 | io.ReadFull(&c1, out1)
50 | tmp := out2[:]
51 | rand.Seed(0xFF43109)
52 | for len(tmp) > 0 {
53 | n := 1 + rand.Intn(256)
54 | if n > len(tmp) {
55 | n = len(tmp)
56 | }
57 | n, err := c2.Read(tmp[:n])
58 | fatalOnErr(err, "CounterEncryptorRand.Read", t)
59 | tmp = tmp[n:]
60 | }
61 | if !bytes.Equal(out1, out2) {
62 | t.Error("identical CSPRNG does not produce the same output")
63 | }
64 | }
65 |
66 | func stddev(data []int) float64 {
67 | var sum, sum_sqr float64 = 0, 0
68 | for _, h := range data {
69 | sum += float64(h)
70 | sum_sqr += float64(h) * float64(h)
71 | }
72 | n := float64(len(data))
73 | variance := (sum_sqr - ((sum * sum) / n)) / (n - 1)
74 | return math.Sqrt(variance)
75 | }
76 |
77 | func TestCounterEncStreamHistogram(t *testing.T) {
78 | k, err := rsa.GenerateKey(&RandSeedReader{*rand.New(rand.NewSource(0xFF43109))}, 128)
79 | fatalOnErr(err, "rsa.GenerateKey", t)
80 | c, err := goproxy.NewCounterEncryptorRandFromKey(k, []byte("the quick brown fox run over the lazy dog"))
81 | fatalOnErr(err, "NewCounterEncryptorRandFromKey", t)
82 | nout := 100 * 1000
83 | out := make([]byte, nout)
84 | io.ReadFull(&c, out)
85 | refhist := make([]int, 256)
86 | for i := 0; i < nout; i++ {
87 | refhist[rand.Intn(256)]++
88 | }
89 | hist := make([]int, 256)
90 | for _, b := range out {
91 | hist[int(b)]++
92 | }
93 | refstddev, stddev := stddev(refhist), stddev(hist)
94 | // due to lack of time, I guestimate
95 | t.Logf("ref:%v - act:%v = %v", refstddev, stddev, math.Abs(refstddev-stddev))
96 | if math.Abs(refstddev-stddev) >= 1 {
97 | t.Errorf("stddev of ref histogram different than regular PRNG: %v %v", refstddev, stddev)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/vendor/github.com/elazarl/goproxy/ctx.go:
--------------------------------------------------------------------------------
1 | package goproxy
2 |
3 | import (
4 | "net/http"
5 | "regexp"
6 | )
7 |
8 | // ProxyCtx is the Proxy context, contains useful information about every request. It is passed to
9 | // every user function. Also used as a logger.
10 | type ProxyCtx struct {
11 | // Will contain the client request from the proxy
12 | Req *http.Request
13 | // Will contain the remote server's response (if available. nil if the request wasn't send yet)
14 | Resp *http.Response
15 | RoundTripper RoundTripper
16 | // will contain the recent error that occured while trying to send receive or parse traffic
17 | Error error
18 | // A handle for the user to keep data in the context, from the call of ReqHandler to the
19 | // call of RespHandler
20 | UserData interface{}
21 | // Will connect a request to a response
22 | Session int64
23 | proxy *ProxyHttpServer
24 | }
25 |
26 | type RoundTripper interface {
27 | RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error)
28 | }
29 |
30 | type RoundTripperFunc func(req *http.Request, ctx *ProxyCtx) (*http.Response, error)
31 |
32 | func (f RoundTripperFunc) RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) {
33 | return f(req, ctx)
34 | }
35 |
36 | func (ctx *ProxyCtx) RoundTrip(req *http.Request) (*http.Response, error) {
37 | if ctx.RoundTripper != nil {
38 | return ctx.RoundTripper.RoundTrip(req, ctx)
39 | }
40 | return ctx.proxy.Tr.RoundTrip(req)
41 | }
42 |
43 | func (ctx *ProxyCtx) printf(msg string, argv ...interface{}) {
44 | ctx.proxy.Logger.Printf("[%03d] "+msg+"\n", append([]interface{}{ctx.Session & 0xFF}, argv...)...)
45 | }
46 |
47 | // Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter
48 | // This message will be printed only if the Verbose field of the ProxyHttpServer is set to true
49 | //
50 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){
51 | // nr := atomic.AddInt32(&counter,1)
52 | // ctx.Printf("So far %d requests",nr)
53 | // return r, nil
54 | // })
55 | func (ctx *ProxyCtx) Logf(msg string, argv ...interface{}) {
56 | if ctx.proxy.Verbose {
57 | ctx.printf("INFO: "+msg, argv...)
58 | }
59 | }
60 |
61 | // Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter
62 | // This message will always be printed.
63 | //
64 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){
65 | // f,err := os.OpenFile(cachedContent)
66 | // if err != nil {
67 | // ctx.Warnf("error open file %v: %v",cachedContent,err)
68 | // return r, nil
69 | // }
70 | // return r, nil
71 | // })
72 | func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{}) {
73 | ctx.printf("WARN: "+msg, argv...)
74 | }
75 |
76 | var charsetFinder = regexp.MustCompile("charset=([^ ;]*)")
77 |
78 | // Will try to infer the character set of the request from the headers.
79 | // Returns the empty string if we don't know which character set it used.
80 | // Currently it will look for charset=