add more detail info for routing

This commit is contained in:
ginuerzh 2018-12-06 19:57:36 +08:00
parent 0bb52bc7bc
commit 7686a4bdc8
26 changed files with 592 additions and 561 deletions

View File

@ -152,7 +152,7 @@ func NewBypassPatterns(reversed bool, patterns ...string) *Bypass {
// Contains reports whether the bypass includes addr.
func (bp *Bypass) Contains(addr string) bool {
if bp == nil {
if bp == nil || addr == "" {
return false
}
// try to strip the port

View File

@ -1,9 +1,7 @@
package gost
import (
"bytes"
"errors"
"fmt"
"net"
"time"
@ -20,6 +18,7 @@ type Chain struct {
isRoute bool
Retries int
nodeGroups []*NodeGroup
route []Node // nodes in the selected route
}
// NewChain creates a proxy chain with a list of proxy nodes.
@ -197,18 +196,14 @@ func (c *Chain) Conn(opts ...ChainOption) (conn net.Conn, err error) {
continue
}
conn, err = route.getConn()
if err != nil {
log.Log(err)
continue
}
if err == nil {
break
}
}
return
}
// getConn obtains a connection to the last node of the chain.
// It does not handshake with the last node.
func (c *Chain) getConn() (conn net.Conn, err error) {
if c.IsEmpty() {
err = ErrEmptyChain
@ -256,35 +251,7 @@ func (c *Chain) getConn() (conn net.Conn, err error) {
}
func (c *Chain) selectRoute() (route *Chain, err error) {
if c.IsEmpty() || c.isRoute {
return c, nil
}
buf := bytes.Buffer{}
route = newRoute()
for _, group := range c.nodeGroups {
node, err := group.Next()
if err != nil {
return nil, err
}
buf.WriteString(fmt.Sprintf("%s -> ", node.String()))
if node.Client.Transporter.Multiplex() {
node.DialOptions = append(node.DialOptions,
ChainDialOption(route),
)
route = newRoute() // cutoff the chain for multiplex.
}
route.AddNode(node)
}
route.Retries = c.Retries
if Debug {
log.Log("select route:", buf.String())
}
return
return c.selectRouteFor("")
}
// selectRouteFor selects route with bypass testing.
@ -293,8 +260,8 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
return c, nil
}
buf := bytes.Buffer{}
route = newRoute()
var nl []Node
for _, group := range c.nodeGroups {
var node Node
@ -304,28 +271,21 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
}
if node.Bypass.Contains(addr) {
if Debug {
buf.WriteString(fmt.Sprintf("[bypass]%s -> %s", node.String(), addr))
log.Log("[route]", buf.String())
break
}
return
}
buf.WriteString(fmt.Sprintf("%s -> ", node.String()))
if node.Client.Transporter.Multiplex() {
node.DialOptions = append(node.DialOptions,
ChainDialOption(route),
)
route = newRoute() // cutoff the chain for multiplex.
route = newRoute() // cutoff the chain for multiplex node.
}
route.AddNode(node)
nl = append(nl, node)
}
route.Retries = c.Retries
buf.WriteString(addr)
log.Log("[route]", buf.String())
route.route = nl
return
}

View File

@ -0,0 +1 @@
Hello World!

View File

@ -1,21 +0,0 @@
{
"key": "it's a secrect",
"crypt": "aes",
"mode": "fast",
"mtu" : 1350,
"sndwnd": 1024,
"rcvwnd": 1024,
"datashard": 10,
"parityshard": 3,
"dscp": 0,
"nocomp": false,
"acknodelay": false,
"nodelay": 0,
"interval": 40,
"resend": 0,
"nc": 0,
"sockbuf": 4194304,
"keepalive": 10,
"snmplog": "",
"snmpperiod": 60
}

View File

@ -407,7 +407,8 @@ func (r *route) GenRouters() ([]router, error) {
hosts := parseHosts(node.Get("hosts"))
handler.Init(
gost.AddrHandlerOption(node.Addr),
// gost.AddrHandlerOption(node.Addr),
gost.AddrHandlerOption(ln.Addr().String()),
gost.ChainHandlerOption(chain),
gost.UsersHandlerOption(users...),
gost.TLSConfigHandlerOption(tlsCfg),
@ -417,9 +418,10 @@ func (r *route) GenRouters() ([]router, error) {
gost.BypassHandlerOption(node.Bypass),
gost.ResolverHandlerOption(resolver),
gost.HostsHandlerOption(hosts),
gost.RetryHandlerOption(node.GetInt("retry")),
gost.RetryHandlerOption(node.GetInt("retry")), // override the global retry option.
gost.TimeoutHandlerOption(time.Duration(node.GetInt("timeout"))*time.Second),
gost.ProbeResistHandlerOption(node.Get("probe_resist")),
gost.NodeHandlerOption(node),
)
rt := router{
@ -446,7 +448,7 @@ type router struct {
}
func (r *router) Serve() error {
log.Logf("[route] start %s on %s", r.node.String(), r.server.Addr())
log.Logf("%s on %s", r.node.String(), r.server.Addr())
return r.server.Serve(r.handler)
}

View File

@ -1,48 +0,0 @@
[//]: <> (https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309)
# Create Root CA (Done once)
## Create Root Key
**Attention:** this is the key used to sign the certificate requests, anyone holding this can sign certificates on your behalf. So keep it in a safe place!
```bash
openssl genrsa -des3 -out rootCA.key 4096
```
If you want a non password protected key just remove the `-des3` option
## Create and self sign the Root Certificate
```bash
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
```
Here we used our root key to create the root certificate that needs to be distributed in all the computers that have to trust us.
# Create a certificate (Done for each server)
This procedure needs to be followed for each server/appliance that needs a trusted certificate from our CA
## Create the certificate key
```
openssl genrsa -out mydomain.com.key 2048
```
## Create the signing request
**Important:** Please mind that while creating the signign request is important to specify the `Common Name` providing the IP address or URL for the service, otherwise the certificate
cannot be verified
```
openssl req -new -key mydomain.com.key -out mydomain.com.csr
```
## Generate the certificate using the `mydomain` csr and key along with the CA Root key
```
openssl x509 -req -in mydomain.com.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out mydomain.com.crt -days 500 -sha256
```

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDvjCCAaYCCQC0XjV3wljvnjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMTgwNzA4MDQ1MzIyWhcNMTkxMTIwMDQ1MzIyWjAuMQswCQYD
VQQGEwJDTjELMAkGA1UEBwwCU0gxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMOKgzWil/KjyRy2Axb3XlLB1nMwLFJC
pC6r8yb+1Kq/ldZghJZvymuFVjn+bihvJqvZiOv4KRtnM8gD55AhaQp6Ese5M9b+
47HLB//SkfJsQREsmnrHfHxjmUQjhMy7jrpcf9OnDOXQ5zk3v6AWEIqMtAiZ99ku
AQvyJJ07+VpwZrMuzbSGfFBCKEbbqP7yKHjSUm3QDTpTiK4AnBmzlVeThUIA68oa
XZKQVXX/8U2i6H4eq5eNpyUsKSnnuK+cryHpAIK4vNMzw96vATTfEmuWASEzkHhW
3KtfXE0CIH0GsK5zueGDo9ygnO7hjtx60SWynlGf6c6edxPwNvEmTZcCAwEAATAN
BgkqhkiG9w0BAQsFAAOCAgEApLkdhnDzErgBljY6qRaR0JlouTpqJXwi5BRi7F1P
bx5ukrZAVSOsZ7ncEkZuxkIX+ktBVFBL8twkvMEl+sMQ24R+F+TrlHWN2xPR/pez
9V19hq26yMIlYLqSq3KZ0W9ZlT2ge+3sTvY+gAJhZ6nOz9WGRJ1mi+pN/ok678QX
KdOJXcePzYr5iKqMq/5cJ2sA1xYwVl+0xrvfRVTFkp4yR6wzGODtjquB+scZ9S64
GWnFTjHAJvUKYxpeoLAt9lZHsESDqGq7hA4z1uVjhNEDJHKnXW4OhXxMB8Gk2hY8
3k4zbnKsouNNW0a7jijCMpXOem/vgQF4GK5ecp0S+Ml/AunsPoi6rGgOCX8XXmti
6DfQhsxxgn1co/JKNxhgsnQftXFwKivh73JFctSh+bMLsewfXsvq+b0K3EuuV9bV
EttVCgbUaCDYdA6IDkqD2PRx9tsotne76r+cX+ah+NjnA6XN+XY2bJgV1UaiKTrP
moNHglw+xoUqOJ7FlGJcVC7uIFPhMviNkpSZh6WxX+OSS4fPO25kxxNpldql6I+3
xb5XEHLpPCEI4PyK0rYnsjk764Loqff8YBMFRQSXIUz9ot5SgGs/FY1vsQap5OeD
Hw2usWhCvkSzr7kiXI+30BvJKK2r9GOAM7mtO9dfkM9MMKKnMzd+O2XE4r6PNLrg
Rds=
-----END CERTIFICATE-----

View File

@ -1,16 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICczCCAVsCAQAwLjELMAkGA1UEBhMCQ04xCzAJBgNVBAcMAlNIMRIwEAYDVQQD
DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDioM1
opfyo8kctgMW915SwdZzMCxSQqQuq/Mm/tSqv5XWYISWb8prhVY5/m4obyar2Yjr
+CkbZzPIA+eQIWkKehLHuTPW/uOxywf/0pHybEERLJp6x3x8Y5lEI4TMu466XH/T
pwzl0Oc5N7+gFhCKjLQImffZLgEL8iSdO/lacGazLs20hnxQQihG26j+8ih40lJt
0A06U4iuAJwZs5VXk4VCAOvKGl2SkFV1//FNouh+HquXjaclLCkp57ivnK8h6QCC
uLzTM8PerwE03xJrlgEhM5B4VtyrX1xNAiB9BrCuc7nhg6PcoJzu4Y7cetElsp5R
n+nOnncT8DbxJk2XAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAr+AkYRAPulBU
B5HR3pAreYrf3Y2fvGLSNo4hvsJkmXJxDgMZnGsjVzW1IZLF8szn4v050y6Qm/Ne
qupabYP5zpj0vKkACYGJ2zadnowmwlTzwlxEOv27uQykC/IuRcjdloAD7ZwhNwmO
dLNjdiXn63GUeSL/JK0UHyXTqvpmiHq+6TAOdl3vmsRFCQDChRtViK2fwSeX2y87
hLicSVQyNOe0gUx7IvE9B2QPNhdzaMVPYeN8I/cayNeUKhiWxEGKhwPAaievuSXJ
fUsz11XYBYW+kjFsTqkV1OjkG0mxvwaiq5W3CRx8365w71IMdKV5t5xhc0n0TXp7
cT27XN7cdw==
-----END CERTIFICATE REQUEST-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAw4qDNaKX8qPJHLYDFvdeUsHWczAsUkKkLqvzJv7Uqr+V1mCE
lm/Ka4VWOf5uKG8mq9mI6/gpG2czyAPnkCFpCnoSx7kz1v7jscsH/9KR8mxBESya
esd8fGOZRCOEzLuOulx/06cM5dDnOTe/oBYQioy0CJn32S4BC/IknTv5WnBmsy7N
tIZ8UEIoRtuo/vIoeNJSbdANOlOIrgCcGbOVV5OFQgDryhpdkpBVdf/xTaLofh6r
l42nJSwpKee4r5yvIekAgri80zPD3q8BNN8Sa5YBITOQeFbcq19cTQIgfQawrnO5
4YOj3KCc7uGO3HrRJbKeUZ/pzp53E/A28SZNlwIDAQABAoIBAGx1pMeYMw3L2R5K
urX/aVsf1xI3My5Bdo3IpGsJx+4ZrEOnb4N96FnxMF2kiXd2B44kb/TqxepEOQ2F
VOi2D2xXP5l2WZGz+ZnBUuOL6ZX8g67B/cGCasMX/4gy51Mj6UvnSKOeMeI7GDW9
fVWPR4eB+c4XkMju4ne8zKBGBs4pN4KoxTWSnZSM4p+q/Jb/DMa+kVhFfRjkqfWc
vCpDgHs1uMcHvPBNYO9flDaC2Jgk4cvV9mX0TolXAvaNo8aN0joM7WH3fvw7NCD9
LCkqCmpjOxJIqJQT1twIkSy42q7VaFi7ApyIaMfXlmnj4UTlVTe5bBO+2AgwLYtC
cKgDMjECgYEA8JPm3Pc80EsYB6d4qp/Qmy2VrnlaxZwvaRwh63Pssqthg4SZkIp5
yjXOT4MDlJdrEzMtATRZUXTCRxGFSs0tolNY2KQ2WvYRhISlN8UBkGuMEkRGLuct
p++qpPcSZJcox25kT82CKin1nQYb48k33JAOMUOWIBJO56G35sfPj28CgYEA0BOE
pa+FYj/WxZS79YT1ZbsajeuUKlNUtAIxKJ2cKSQyfFuPM+xZG3H+iroRfR8HCVai
2+Oz9/TlxZOPR7+P+2fpS8W2tT+Qkmiyz8QJAULd+Irw5XIdatkpVm343XxMx3Pa
2qtBmgj6RINvsWTWRotMqhcuDRirxqm1IIQhkFkCgYBLNmIhyOXpVODRW8k8xrQI
H6tBHc2EJD0qRlJQczCX9z6ISIdeCfzjfAjhENuos+IU4ZX7X2thLPikEVUzuou+
yQHo0QXxUCbP4Exq8Bt6FDV5bIDonvvGGgamhlvouN1V5CxWSrCcD/wquEM15q2h
NiRJwJCJvE+Q2R1OeD9q3wKBgFWDkAJf7luAjQ3KoKy4pfnXOYSWCuCSOr94Hyfo
DmPCIpWFM4dNXRmwccIl0kYv2D54QppILJB9L2lRyZLdIZlbDUA802gN5aamLMbC
dEj2aC9bOsGxcnGVKi4BKEQub4eRD6LKuz1I70H1GpQ3MvDvEuTcfeqX9xDAclYY
t4qRAoGBAI6YSTs97DUe7Zwk7q+S3PBU5uct4Dwtmy2XWZdgHwl5aP8apSLciL5Y
PMkpcTMzkuC+QFaPZ8wFcI7GLg0bOs91hkrqscDKEg4nGB9fJkU82iOQZNL4Hv1u
wO7uIGa2kcpNtQOLNO88y45WFyrn5a+T6VhDmIuc+F+TU1ZzdYdH
-----END RSA PRIVATE KEY-----

View File

@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEpDCCAowCCQDwV08QFUCcSzANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMTgwNzA4MDQ1MzE3WhcNMjEwNDI3MDQ1MzE3WjAUMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDE
+71yX9vQY3l52C31e04ACvm2oNMLSCrLOXGewOTFpv9yXjinMC0Ab6Xa4yB4MPtd
ujWDSEq9gkKCkILoalVX7R4gtLDN+EdoVadBw/WHbrGB4sHnFOWwpUbjiiwwPSU5
qXjcqIqR2sA1BgoAv6c1qHq7V4bgbEjtGL71KkDoQZSIgNyJlXe1mcUKqmqeAnro
0WfwrNXyYt66L3PmCy9MIpWRxf9sa8PDsgT3SQEN4BHb70Z8hNj6RXfVGDZcpfcI
iwbrL//YnK7waRKaKD4LoLOodE0cx3fowSWYvlwUAoYx8wFKOcdtM1zaUp+QDAug
xT5g5ghU150XuqhDU6Wq1An8dLgcDU1D4cxhLk/W8OXtIk4k7yny6eUJi2zHziMm
8jfHd3M6SwohUrE3LsQI5gpvu4sAVFLMkRxaWZ95XhsVMmIsE/L5FHwDfqid0dvx
bafOKT+fI3N3BaUPJlVHCNqSzSZIW59+ufnDwBV7SmJj4KMlvixEU+EFfPFdGiCA
Lr0dSG5+Scx1aClaMUeVccCljp2f99IEa9wI+xwMPDStkOmnhVuqG1aEogggQZkD
/5yh04wrn8EwYCAiasNNUXTV7AoqIt2bgeFbGo2Qr7LdsYuUmaWEzTm0KsHogkkg
Ibd3RPBLDr/WfWI13oHMdsz8jjbXG/D1AhrcdozYDQIDAQABMA0GCSqGSIb3DQEB
CwUAA4ICAQC1EeQqn2AwrS+UVc5fKRpHzV9ZMiDpxFMRLsDWBP5kNr1nSA72yYcR
WgxvdqG/rGRds6lvRbvIaWD0zeujPkR3iCpb1V5oRXQ6lWOlY44pZEwCdnDd2M8I
yQ7BLZCHHmlCN7a51n2o0D78HeILIeeTCQlKFDc5r51qrZbZR5DZmrp9jaZ+3eCg
LQ3Onfj0WEmQFuMFGQrbJ2oaCC1GvuZWEbRh+lrxjRKOyCaRQFTY4Efe8tIwMm6J
1iyMtqK7BxminQCfizQrstB67wMljydYeUf+wwbgkiKGYc9VGopckrO3lntzKycu
9l0BmlZYkmCFt3cv23BcqAbcLdyLXh3yASwVMXaLZ4iVSaslRm4uX+gbKFCBABLa
vqu7JQHfAPOeYj7zCrN12EHejPxdCjSImBeAbe56vax4uFGAodXxDGcepRItSzax
qPKJd8U/8e3JDn+wmZNKwD9UGLZPbiuYOg7X+EWhjki0J6ZjgLc8dMleeD2rO+j2
P/Wgv1gMr6J1svUlqkNf1Ng9eSbl/nMhuOBVOGcPnK7+wCLxM7ByaR0QgeH6/9VO
4urq53/vspBC679BHsZx3gIhcg4VefmOM2cZnTRM4izPstq1JBQkbuvz+5XuT7Yj
5Fk1/xkapCUifntKYSoslkkbNHRYxAInqkc0txn3qNBI8GAQFksz5g==
-----END CERTIFICATE-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1 +0,0 @@
B45E3577C258EF9E

View File

@ -33,6 +33,7 @@ type HandlerOptions struct {
Resolver Resolver
Hosts *Hosts
ProbeResist string
Node Node
}
// HandlerOption allows a common way to set handler options.
@ -129,6 +130,13 @@ func ProbeResistHandlerOption(pr string) HandlerOption {
}
}
// NodeHandlerOption set the server node for server handler.
func NodeHandlerOption(node Node) HandlerOption {
return func(opts *HandlerOptions) {
opts.Node = node
}
}
type autoHandler struct {
options *HandlerOptions
}

276
http.go
View File

@ -2,6 +2,7 @@ package gost
import (
"bufio"
"bytes"
"encoding/base64"
"fmt"
"net"
@ -108,17 +109,33 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
if req == nil {
return
}
if Debug {
dump, _ := httputil.DumpRequest(req, false)
log.Logf("[http] %s -> %s\n%s", conn.RemoteAddr(), req.Host, string(dump))
}
host := req.Host
// try to get the actual host.
if v := req.Header.Get("Gost-Target"); v != "" {
if host, err := decodeServerName(v); err == nil {
if h, err := decodeServerName(v); err == nil {
host = h
}
}
if _, port, _ := net.SplitHostPort(host); port == "" {
host = net.JoinHostPort(host, "80")
}
u, _, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
if u != "" {
u += "@"
}
log.Logf("[http] %s%s -> %s -> %s",
u, conn.RemoteAddr(), h.options.Node.String(), host)
if Debug {
dump, _ := httputil.DumpRequest(req, false)
log.Logf("[http] %s -> %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
req.Host = host
}
}
req.Header.Del("Gost-Target")
resp := &http.Response{
ProtoMajor: 1,
@ -127,38 +144,147 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
}
resp.Header.Add("Proxy-Agent", "gost/"+Version)
if !Can("tcp", req.Host, h.options.Whitelist, h.options.Blacklist) {
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[http] %s - %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), req.Host, req.Host)
conn.RemoteAddr(), conn.LocalAddr(), host)
resp.StatusCode = http.StatusForbidden
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(dump))
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
if h.options.Bypass.Contains(req.Host) {
log.Logf("[http] [bypass] %s", req.Host)
if h.options.Bypass.Contains(host) {
resp.StatusCode = http.StatusForbidden
log.Logf("[http] %s - %s bypass %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(dump))
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
if !h.authenticate(conn, req, resp) {
return
}
if req.Method == "PRI" || (req.Method != http.MethodConnect && req.URL.Scheme != "http") {
resp.StatusCode = http.StatusBadRequest
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
req.Header.Del("Proxy-Authorization")
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var err error
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(host)
if err != nil {
log.Logf("[http] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
conn.RemoteAddr(), h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", host)
log.Log("[route]", buf.String())
// forward http request
lastNode := route.LastNode()
if req.Method != http.MethodConnect && lastNode.Protocol == "http" {
err = h.forwardRequest(conn, req, route)
if err == nil {
return
}
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
cc, err = route.Dial(host,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
}
if err != nil {
resp.StatusCode = http.StatusServiceUnavailable
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
defer cc.Close()
if req.Method == http.MethodConnect {
b := []byte("HTTP/1.1 200 Connection established\r\n" +
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
if Debug {
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(b))
}
conn.Write(b)
} else {
req.Header.Del("Proxy-Connection")
if err = req.Write(cc); err != nil {
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
}
log.Logf("[http] %s <-> %s", conn.RemoteAddr(), host)
transport(conn, cc)
log.Logf("[http] %s >-< %s", conn.RemoteAddr(), host)
}
func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response) (ok bool) {
u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
if Debug && (u != "" || p != "") {
log.Logf("[http] %s - %s : Authorization: '%s' '%s'", conn.RemoteAddr(), req.Host, u, p)
log.Logf("[http] %s -> %s : Authorization '%s' '%s'",
conn.RemoteAddr(), conn.LocalAddr(), u, p)
}
if !authenticate(u, p, h.options.Users...) {
if authenticate(u, p, h.options.Users...) {
return true
}
// probing resistance is enabled
if ss := strings.SplitN(h.options.ProbeResist, ":", 2); len(ss) == 2 {
switch ss[0] {
@ -178,9 +304,11 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
defer cc.Close()
req.Write(cc)
log.Logf("[http] %s <-> %s : forward to %s", conn.LocalAddr(), req.Host, ss[1])
log.Logf("[http] %s <-> %s : forward to %s",
conn.RemoteAddr(), conn.LocalAddr(), ss[1])
transport(conn, cc)
log.Logf("[http] %s >-< %s : forward to %s", conn.LocalAddr(), req.Host, ss[1])
log.Logf("[http] %s >-< %s : forward to %s",
conn.RemoteAddr(), conn.LocalAddr(), ss[1])
return
}
case "file":
@ -190,22 +318,21 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
if finfo, _ := f.Stat(); finfo != nil {
resp.ContentLength = finfo.Size()
}
resp.Header.Set("Content-Type", "text/html")
resp.Body = f
}
}
}
if resp.StatusCode == 0 {
log.Logf("[http] %s <- %s : proxy authentication required", conn.RemoteAddr(), req.Host)
log.Logf("[http] %s <- %s : proxy authentication required",
conn.RemoteAddr(), conn.LocalAddr())
resp.StatusCode = http.StatusProxyAuthRequired
resp.Header.Add("Proxy-Authenticate", "Basic realm=\"gost\"")
} else {
resp.Header = http.Header{}
resp.Header.Set("Server", "nginx/1.14.1")
resp.Header.Set("Date", time.Now().Format(http.TimeFormat))
if resp.ContentLength > 0 {
resp.Header.Set("Content-Type", "text/html")
}
if resp.StatusCode == http.StatusOK {
resp.Header.Set("Connection", "keep-alive")
}
@ -213,120 +340,21 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(dump))
log.Logf("[http] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
if req.Method == "PRI" || (req.Method != http.MethodConnect && req.URL.Scheme != "http") {
resp.StatusCode = http.StatusBadRequest
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(dump))
}
resp.Write(conn)
return
}
req.Header.Del("Proxy-Authorization")
host := req.Host
if _, port, _ := net.SplitHostPort(host); port == "" {
host = net.JoinHostPort(req.Host, "80")
}
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var err error
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(req.Host)
if err != nil {
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
continue
}
// forward http request
lastNode := route.LastNode()
if req.Method != http.MethodConnect && lastNode.Protocol == "http" {
err = h.forwardRequest(conn, req, route)
if err == nil {
return
}
// log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
continue
}
cc, err = route.Dial(host,
RetryChainOption(1),
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
}
if err != nil {
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), host, err)
resp.StatusCode = http.StatusServiceUnavailable
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), host, string(dump))
}
resp.Write(conn)
return
}
defer cc.Close()
if req.Method == http.MethodConnect {
b := []byte("HTTP/1.1 200 Connection established\r\n" +
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
if Debug {
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), host, string(b))
}
conn.Write(b)
} else {
req.Header.Del("Proxy-Connection")
if err = req.Write(cc); err != nil {
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), host, err)
return
}
}
var su string
if u != "" {
su = u + "@"
}
log.Logf("[http] %s%s <-> %s", su, cc.LocalAddr(), host)
transport(conn, cc)
log.Logf("[http] %s%s >-< %s", su, cc.LocalAddr(), host)
}
func (h *httpHandler) forwardRequest(conn net.Conn, req *http.Request, route *Chain) error {
if route.IsEmpty() {
return nil
}
lastNode := route.LastNode()
cc, err := route.Conn(
RetryChainOption(1), // we control the retry manually.
)
cc, err := route.Conn()
if err != nil {
return err
}
@ -346,7 +374,7 @@ func (h *httpHandler) forwardRequest(conn net.Conn, req *http.Request, route *Ch
req.URL.Scheme = "http" // make sure that the URL is absolute
}
if err = req.WriteProxy(cc); err != nil {
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return nil
}
cc.SetWriteDeadline(time.Time{})

206
http2.go
View File

@ -6,6 +6,7 @@ import (
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
@ -50,6 +51,7 @@ func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectO
Host: cc.addr,
ContentLength: -1,
}
// TODO: use the standard CONNECT method.
req.Header.Set("Gost-Target", addr)
if c.User != nil {
u := c.User.Username()
@ -110,8 +112,20 @@ func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn,
}
tr.clientMutex.Lock()
defer tr.clientMutex.Unlock()
client, ok := tr.clients[addr]
if !ok {
// NOTE: due to the dummy connection, HTTP2 node in a proxy chain can not be marked as dead.
// There is no real connection to the HTTP2 server at this moment.
// So we should try to connect the server.
conn, err := opts.Chain.Dial(addr)
if err != nil {
return nil, err
}
conn.Close()
transport := http2.Transport{
TLSClientConfig: tr.tlsConfig,
DialTLS: func(network, adr string, cfg *tls.Config) (net.Conn, error) {
@ -128,7 +142,6 @@ func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn,
}
tr.clients[addr] = client
}
tr.clientMutex.Unlock()
return &http2ClientConn{
addr: addr,
@ -283,31 +296,40 @@ func (h *http2Handler) Handle(conn net.Conn) {
}
func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
target := r.Header.Get("Gost-Target")
if target == "" {
target = r.Host
host := r.Header.Get("Gost-Target")
if host == "" {
host = r.Host
}
if !strings.Contains(target, ":") {
target += ":80"
if _, port, _ := net.SplitHostPort(host); port == "" {
host = net.JoinHostPort(host, "80")
}
laddr := h.options.Addr
u, _, _ := basicProxyAuth(r.Header.Get("Proxy-Authorization"))
if u != "" {
u += "@"
}
log.Logf("[http2] %s%s -> %s -> %s",
u, r.RemoteAddr, h.options.Node.String(), host)
if Debug {
log.Logf("[http2] %s %s - %s %s", r.Method, r.RemoteAddr, target, r.Proto)
dump, _ := httputil.DumpRequest(r, false)
log.Log("[http2]", string(dump))
log.Logf("[http2] %s - %s\n%s", r.RemoteAddr, laddr, string(dump))
}
w.Header().Set("Proxy-Agent", "gost/"+Version)
if !Can("tcp", target, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[http2] Unauthorized to tcp connect to %s", target)
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[http2] %s - %s : Unauthorized to tcp connect to %s",
r.RemoteAddr, laddr, host)
w.WriteHeader(http.StatusForbidden)
return
}
if h.options.Bypass.Contains(target) {
log.Logf("[http2] [bypass] %s", target)
if h.options.Bypass.Contains(host) {
log.Logf("[http2] %s - %s bypass %s",
r.RemoteAddr, laddr, host)
w.WriteHeader(http.StatusForbidden)
return
}
@ -319,11 +341,105 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
}
if !h.authenticate(w, r, resp) {
return
}
// delete the proxy related headers.
r.Header.Del("Proxy-Authorization")
r.Header.Del("Proxy-Connection")
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var err error
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(host)
if err != nil {
log.Logf("[http2] %s -> %s : %s",
r.RemoteAddr, laddr, err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
r.RemoteAddr, h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", host)
log.Log("[route]", buf.String())
cc, err = route.Dial(host,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, laddr, err)
}
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
defer cc.Close()
if r.Method == http.MethodConnect {
w.WriteHeader(http.StatusOK)
if fw, ok := w.(http.Flusher); ok {
fw.Flush()
}
// compatible with HTTP1.x
if hj, ok := w.(http.Hijacker); ok && r.ProtoMajor == 1 {
// we take over the underly connection
conn, _, err := hj.Hijack()
if err != nil {
log.Logf("[http2] %s -> %s : %s",
r.RemoteAddr, laddr, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer conn.Close()
log.Logf("[http2] %s <-> %s : downgrade to HTTP/1.1", r.RemoteAddr, host)
transport(conn, cc)
log.Logf("[http2] %s >-< %s", r.RemoteAddr, host)
return
}
log.Logf("[http2] %s <-> %s", r.RemoteAddr, host)
transport(&readWriter{r: r.Body, w: flushWriter{w}}, cc)
log.Logf("[http2] %s >-< %s", r.RemoteAddr, host)
return
}
log.Logf("[http2] %s <-> %s", r.RemoteAddr, host)
if err := h.forwardRequest(w, r, cc); err != nil {
log.Logf("[http2] %s - %s : %s", r.RemoteAddr, host, err)
}
log.Logf("[http2] %s >-< %s", r.RemoteAddr, host)
}
func (h *http2Handler) authenticate(w http.ResponseWriter, r *http.Request, resp *http.Response) (ok bool) {
laddr := h.options.Addr
u, p, _ := basicProxyAuth(r.Header.Get("Proxy-Authorization"))
if Debug && (u != "" || p != "") {
log.Logf("[http2] %s - %s : Authorization: '%s' '%s'", r.RemoteAddr, target, u, p)
log.Logf("[http2] %s - %s : Authorization '%s' '%s'", r.RemoteAddr, laddr, u, p)
}
if authenticate(u, p, h.options.Users...) {
return true
}
if !authenticate(u, p, h.options.Users...) {
// probing resistance is enabled
if ss := strings.SplitN(h.options.ProbeResist, ":", 2); len(ss) == 2 {
switch ss[0] {
@ -341,11 +457,11 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
cc, err := net.Dial("tcp", ss[1])
if err == nil {
defer cc.Close()
log.Logf("[http2] %s <-> %s : forward to %s", r.RemoteAddr, target, ss[1])
log.Logf("[http2] %s <-> %s : forward to %s", r.RemoteAddr, laddr, ss[1])
if err := h.forwardRequest(w, r, cc); err != nil {
log.Logf("[http2] %s - %s : %s", r.RemoteAddr, target, err)
log.Logf("[http2] %s - %s : %s", r.RemoteAddr, laddr, err)
}
log.Logf("[http2] %s >-< %s : forward to %s", r.RemoteAddr, target, ss[1])
log.Logf("[http2] %s >-< %s : forward to %s", r.RemoteAddr, laddr, ss[1])
return
}
case "file":
@ -361,7 +477,7 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
}
if resp.StatusCode == 0 {
log.Logf("[http2] %s <- %s : proxy authentication required", r.RemoteAddr, target)
log.Logf("[http2] %s <- %s : proxy authentication required", r.RemoteAddr, laddr)
resp.StatusCode = http.StatusProxyAuthRequired
resp.Header.Add("Proxy-Authenticate", "Basic realm=\"gost\"")
} else {
@ -379,7 +495,7 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http2] %s <- %s\n%s", r.RemoteAddr, target, string(dump))
log.Logf("[http2] %s <- %s\n%s", r.RemoteAddr, laddr, string(dump))
}
h.writeResponse(w, resp)
@ -388,58 +504,6 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
return
}
r.Header.Del("Proxy-Authorization")
r.Header.Del("Proxy-Connection")
cc, err := h.options.Chain.Dial(target,
RetryChainOption(h.options.Retries),
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err != nil {
log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
w.WriteHeader(http.StatusServiceUnavailable)
return
}
defer cc.Close()
if r.Method == http.MethodConnect {
w.WriteHeader(http.StatusOK)
if fw, ok := w.(http.Flusher); ok {
fw.Flush()
}
// compatible with HTTP1.x
if hj, ok := w.(http.Hijacker); ok && r.ProtoMajor == 1 {
// we take over the underly connection
conn, _, err := hj.Hijack()
if err != nil {
log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer conn.Close()
log.Logf("[http2] %s <-> %s : downgrade to HTTP/1.1", r.RemoteAddr, target)
transport(conn, cc)
log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
return
}
log.Logf("[http2] %s <-> %s", r.RemoteAddr, target)
transport(&readWriter{r: r.Body, w: flushWriter{w}}, cc)
log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
return
}
log.Logf("[http2] %s <-> %s", r.RemoteAddr, target)
if err := h.forwardRequest(w, r, cc); err != nil {
log.Logf("[http2] %s - %s : %s", r.RemoteAddr, target, err)
}
log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
}
func (h *http2Handler) forwardRequest(w http.ResponseWriter, r *http.Request, rw io.ReadWriter) (err error) {
if err = r.Write(rw); err != nil {
return

View File

@ -21,7 +21,7 @@ type Node struct {
Protocol string
Transport string
Remote string // remote address, used by tcp/udp port forwarding
url string // raw url
url *url.URL // raw url
User *url.Userinfo
Values url.Values
DialOptions []DialOption
@ -55,10 +55,11 @@ func ParseNode(s string) (node Node, err error) {
Values: u.Query(),
User: u.User,
marker: &failMarker{},
url: u,
}
u.RawQuery = ""
node.url = u.String()
u.User = nil
schemes := strings.Split(u.Scheme, "+")
if len(schemes) == 1 {
@ -139,7 +140,7 @@ func (node *Node) GetInt(key string) int {
}
func (node Node) String() string {
return node.url
return node.url.String()
}
// NodeGroup is a group of nodes.

View File

@ -173,7 +173,7 @@ func (f *FailFilter) Filter(nodes []Node) []Node {
nl := []Node{}
for i := range nodes {
marker := nodes[i].marker.Clone()
// log.Logf("%s: %d/%d %d/%d", nodes[i], marker.failCount, f.MaxFails, marker.failTime, f.FailTimeout)
// log.Logf("%s: %d/%d %v/%v", nodes[i], marker.failCount, f.MaxFails, marker.failTime, f.FailTimeout)
if marker.failCount < uint32(f.MaxFails) ||
time.Since(time.Unix(marker.failTime, 0)) >= f.FailTimeout {
nl = append(nl, nodes[i])

75
sni.go
View File

@ -8,6 +8,7 @@ import (
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"io"
"net"
@ -55,22 +56,23 @@ func (h *sniHandler) Init(options ...HandlerOption) {
}
func (h *sniHandler) Handle(conn net.Conn) {
br := bufio.NewReader(conn)
defer conn.Close()
br := bufio.NewReader(conn)
hdr, err := br.Peek(dissector.RecordHeaderLen)
if err != nil {
log.Log("[sni]", err)
conn.Close()
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
conn = &bufferdConn{br: br, Conn: conn}
defer conn.Close()
if hdr[0] != dissector.Handshake {
// We assume it is an HTTP request
req, err := http.ReadRequest(bufio.NewReader(conn))
if err != nil {
log.Logf("[sni] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
if !req.URL.IsAbs() {
@ -84,40 +86,79 @@ func (h *sniHandler) Handle(conn net.Conn) {
b, host, err := readClientHelloRecord(conn, "", false)
if err != nil {
log.Log("[sni]", err)
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
addr := net.JoinHostPort(host, "443")
host = net.JoinHostPort(host, "443")
if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[sni] Unauthorized to tcp connect to %s", addr)
log.Logf("[ss] %s -> %s -> %s",
conn.RemoteAddr(), h.options.Node.String(), host)
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[sni] %s -> %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
return
}
if h.options.Bypass.Contains(addr) {
log.Log("[sni] [bypass]", addr)
if h.options.Bypass.Contains(host) {
log.Log("[sni] %s - %s bypass %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
return
}
cc, err := h.options.Chain.Dial(addr,
RetryChainOption(h.options.Retries),
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(host)
if err != nil {
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
conn.RemoteAddr(), h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", host)
log.Log("[route]", buf.String())
cc, err = route.Dial(host,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
}
if err != nil {
log.Logf("[sni] %s -> %s : %s", conn.RemoteAddr(), addr, err)
return
}
defer cc.Close()
if _, err := cc.Write(b); err != nil {
log.Logf("[sni] %s -> %s : %s", conn.RemoteAddr(), addr, err)
log.Logf("[sni] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
}
log.Logf("[sni] %s <-> %s", cc.LocalAddr(), addr)
log.Logf("[sni] %s <-> %s", cc.LocalAddr(), host)
transport(conn, cc)
log.Logf("[sni] %s >-< %s", cc.LocalAddr(), addr)
log.Logf("[sni] %s >-< %s", cc.LocalAddr(), host)
}
// sniSniffConn is a net.Conn that reads from r, fails on Writes,

197
socks.go
View File

@ -386,12 +386,14 @@ func (h *socks5Handler) Handle(conn net.Conn) {
conn = gosocks5.ServerConn(conn, h.selector)
req, err := gosocks5.ReadRequest(conn)
if err != nil {
log.Log("[socks5]", err)
log.Logf("[socks5] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
if Debug {
log.Logf("[socks5] %s - %s\n%s", conn.RemoteAddr(), req.Addr, req)
log.Logf("[socks5] %s -> %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), req)
}
switch req.Cmd {
case gosocks5.CmdConnect:
@ -410,43 +412,86 @@ func (h *socks5Handler) Handle(conn net.Conn) {
h.handleUDPTunnel(conn, req)
default:
log.Log("[socks5] Unrecognized request:", req.Cmd)
log.Logf("[socks5] %s - %s : Unrecognized request: %d",
conn.RemoteAddr(), conn.LocalAddr(), req.Cmd)
}
}
func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
addr := req.Addr.String()
if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[socks5-connect] Unauthorized to tcp connect to %s", addr)
host := req.Addr.String()
log.Logf("[socks5] %s -> %s -> %s",
conn.RemoteAddr(), h.options.Node.String(), host)
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[socks5] %s - %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks5] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
if h.options.Bypass.Contains(addr) {
log.Logf("[socks5-connect] [bypass] %s", addr)
if h.options.Bypass.Contains(host) {
log.Logf("[socks5] %s - %s : Bypass %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks5] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
cc, err := h.options.Chain.Dial(addr,
RetryChainOption(h.options.Retries),
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var err error
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(host)
if err != nil {
log.Logf("[socks5] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
conn.RemoteAddr(), h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", host)
log.Log("[route]", buf.String())
cc, err = route.Dial(host,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[socks5] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
}
if err != nil {
log.Logf("[socks5-connect] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks5] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
@ -454,22 +499,29 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
if err := rep.Write(conn); err != nil {
log.Logf("[socks5-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
log.Logf("[socks5] %s <- %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
if Debug {
log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks5] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
log.Logf("[socks5-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
log.Logf("[socks5] %s <-> %s", conn.RemoteAddr(), host)
transport(conn, cc)
log.Logf("[socks5-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
log.Logf("[socks5] %s >-< %s", conn.RemoteAddr(), host)
}
func (h *socks5Handler) handleBind(conn net.Conn, req *gosocks5.Request) {
if h.options.Chain.IsEmpty() {
addr := req.Addr.String()
log.Logf("[socks5-bind] %s -> %s -> %s",
conn.RemoteAddr(), h.options.Node.String(), addr)
if h.options.Chain.IsEmpty() {
if !Can("rtcp", addr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("Unauthorized to tcp bind to %s", addr)
log.Logf("[socks5-bind] %s - %s : Unauthorized to tcp bind to %s",
conn.RemoteAddr(), conn.LocalAddr(), addr)
return
}
h.bindOn(conn, addr)
@ -478,11 +530,13 @@ func (h *socks5Handler) handleBind(conn net.Conn, req *gosocks5.Request) {
cc, err := h.options.Chain.Conn()
if err != nil {
log.Logf("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
log.Logf("[socks5-bind] %s <- %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
reply := gosocks5.NewReply(gosocks5.Failure, nil)
reply.Write(conn)
if Debug {
log.Logf("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, reply)
log.Logf("[socks5-bind] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), reply)
}
return
}
@ -492,16 +546,17 @@ func (h *socks5Handler) handleBind(conn net.Conn, req *gosocks5.Request) {
// so we don't need to authenticate it, as it's as explicit as whitelisting
defer cc.Close()
req.Write(cc)
log.Logf("[socks5-bind] %s <-> %s", conn.RemoteAddr(), cc.RemoteAddr())
log.Logf("[socks5-bind] %s <-> %s", conn.RemoteAddr(), addr)
transport(conn, cc)
log.Logf("[socks5-bind] %s >-< %s", conn.RemoteAddr(), cc.RemoteAddr())
log.Logf("[socks5-bind] %s >-< %s", conn.RemoteAddr(), addr)
}
func (h *socks5Handler) bindOn(conn net.Conn, addr string) {
bindAddr, _ := net.ResolveTCPAddr("tcp", addr)
ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error
if err != nil {
log.Logf("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), addr, err)
log.Logf("[socks5-bind] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
return
}
@ -511,14 +566,17 @@ func (h *socks5Handler) bindOn(conn net.Conn, addr string) {
socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
if err := reply.Write(conn); err != nil {
log.Logf("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), addr, err)
log.Logf("[socks5-bind] %s <- %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
ln.Close()
return
}
if Debug {
log.Logf("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), addr, reply)
log.Logf("[socks5-bind] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), reply)
}
log.Logf("[socks5-bind] %s - %s BIND ON %s OK", conn.RemoteAddr(), addr, socksAddr)
log.Logf("[socks5-bind] %s - %s BIND ON %s OK",
conn.RemoteAddr(), conn.LocalAddr(), socksAddr)
var pconn net.Conn
accept := func() <-chan error {
@ -1142,17 +1200,18 @@ func (h *socks4Handler) Handle(conn net.Conn) {
req, err := gosocks4.ReadRequest(conn)
if err != nil {
log.Log("[socks4]", err)
log.Logf("[socks4] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
if Debug {
log.Logf("[socks4] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
log.Logf("[socks4] %s -> %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), req)
}
switch req.Cmd {
case gosocks4.CmdConnect:
log.Logf("[socks4-connect] %s -> %s", conn.RemoteAddr(), req.Addr)
h.handleConnect(conn, req)
case gosocks4.CmdBind:
@ -1160,42 +1219,86 @@ func (h *socks4Handler) Handle(conn net.Conn) {
h.handleBind(conn, req)
default:
log.Logf("[socks4] Unrecognized request: %d", req.Cmd)
log.Logf("[socks4] %s - %s : Unrecognized request: %d",
conn.RemoteAddr(), conn.LocalAddr(), req.Cmd)
}
}
func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) {
addr := req.Addr.String()
log.Logf("[socks4] %s -> %s -> %s",
conn.RemoteAddr(), h.options.Node.String(), addr)
if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[socks4-connect] Unauthorized to tcp connect to %s", addr)
log.Logf("[socks4] %s - %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), conn.LocalAddr(), addr)
rep := gosocks4.NewReply(gosocks4.Rejected, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks4] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
if h.options.Bypass.Contains(addr) {
log.Log("[socks4-connect] [bypass]", addr)
log.Log("[socks4] %s - %s : Bypass %s",
conn.RemoteAddr(), conn.LocalAddr(), addr)
rep := gosocks4.NewReply(gosocks4.Rejected, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks4] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
cc, err := h.options.Chain.Dial(addr,
RetryChainOption(h.options.Retries),
TimeoutChainOption(h.options.Timeout),
)
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var err error
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(addr)
if err != nil {
log.Logf("[socks4] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
conn.RemoteAddr(), h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", addr)
log.Log("[route]", buf.String())
cc, err = route.Dial(addr,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[socks4] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
}
if err != nil {
log.Logf("[socks4-connect] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
rep := gosocks4.NewReply(gosocks4.Failed, nil)
rep.Write(conn)
if Debug {
log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks4] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
return
}
@ -1203,16 +1306,18 @@ func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) {
rep := gosocks4.NewReply(gosocks4.Granted, nil)
if err := rep.Write(conn); err != nil {
log.Logf("[socks4-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
log.Logf("[socks4] %s <- %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
if Debug {
log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
log.Logf("[socks4] %s <- %s\n%s",
conn.RemoteAddr(), conn.LocalAddr(), rep)
}
log.Logf("[socks4-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
log.Logf("[socks4] %s <-> %s", conn.RemoteAddr(), addr)
transport(conn, cc)
log.Logf("[socks4-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
log.Logf("[socks4] %s >-< %s", conn.RemoteAddr(), addr)
}
func (h *socks4Handler) handleBind(conn net.Conn, req *gosocks4.Request) {

65
ss.go
View File

@ -125,49 +125,84 @@ func (h *shadowHandler) Handle(conn net.Conn) {
}
cipher, err := ss.NewCipher(method, password)
if err != nil {
log.Log("[ss]", err)
log.Logf("[ss] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
conn = &shadowConn{conn: ss.NewConn(conn, cipher)}
log.Logf("[ss] %s - %s", conn.RemoteAddr(), conn.LocalAddr())
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
addr, err := h.getRequest(conn)
host, err := h.getRequest(conn)
if err != nil {
log.Logf("[ss] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
log.Logf("[ss] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
// clear timer
conn.SetReadDeadline(time.Time{})
log.Logf("[ss] %s -> %s", conn.RemoteAddr(), addr)
log.Logf("[ss] %s -> %s -> %s",
conn.RemoteAddr(), h.options.Node.String(), host)
if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[ss] Unauthorized to tcp connect to %s", addr)
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[ss] %s - %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
return
}
if h.options.Bypass.Contains(addr) {
log.Logf("[ss] [bypass] %s", addr)
if h.options.Bypass.Contains(host) {
log.Logf("[ss] %s - %s : Bypass %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
return
}
cc, err := h.options.Chain.Dial(addr,
RetryChainOption(h.options.Retries),
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var cc net.Conn
var route *Chain
for i := 0; i < retries; i++ {
route, err = h.options.Chain.selectRouteFor(host)
if err != nil {
log.Logf("[ss] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
continue
}
buf := bytes.Buffer{}
fmt.Fprintf(&buf, "%s -> %s -> ",
conn.RemoteAddr(), h.options.Node.String())
for _, nd := range route.route {
fmt.Fprintf(&buf, "%d@%s -> ", nd.ID, nd.String())
}
fmt.Fprintf(&buf, "%s", host)
log.Log("[route]", buf.String())
cc, err = route.Dial(host,
TimeoutChainOption(h.options.Timeout),
HostsChainOption(h.options.Hosts),
ResolverChainOption(h.options.Resolver),
)
if err == nil {
break
}
log.Logf("[ss] %s -> %s : %s",
conn.RemoteAddr(), conn.LocalAddr(), err)
}
if err != nil {
log.Logf("[ss] %s -> %s : %s", conn.RemoteAddr(), addr, err)
return
}
defer cc.Close()
log.Logf("[ss] %s <-> %s", conn.RemoteAddr(), addr)
log.Logf("[ss] %s <-> %s", conn.RemoteAddr(), host)
transport(conn, cc)
log.Logf("[ss] %s >-< %s", conn.RemoteAddr(), addr)
log.Logf("[ss] %s >-< %s", conn.RemoteAddr(), host)
}
const (

14
ssh.go
View File

@ -444,15 +444,15 @@ func (h *sshForwardHandler) Init(options ...HandlerOption) {
func (h *sshForwardHandler) Handle(conn net.Conn) {
sshConn, chans, reqs, err := ssh.NewServerConn(conn, h.config)
if err != nil {
log.Logf("[ssh-forward] %s -> %s : %s", conn.RemoteAddr(), h.options.Addr, err)
log.Logf("[ssh-forward] %s -> %s : %s", conn.RemoteAddr(), h.options.Node.Addr, err)
conn.Close()
return
}
defer sshConn.Close()
log.Logf("[ssh-forward] %s <-> %s", conn.RemoteAddr(), h.options.Addr)
log.Logf("[ssh-forward] %s <-> %s", conn.RemoteAddr(), h.options.Node.Addr)
h.handleForward(sshConn, chans, reqs)
log.Logf("[ssh-forward] %s >-< %s", conn.RemoteAddr(), h.options.Addr)
log.Logf("[ssh-forward] %s >-< %s", conn.RemoteAddr(), h.options.Node.Addr)
}
func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) {
@ -506,7 +506,7 @@ func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewCha
func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr string) {
defer channel.Close()
log.Logf("[ssh-tcp] %s - %s", h.options.Addr, raddr)
log.Logf("[ssh-tcp] %s - %s", h.options.Node.Addr, raddr)
if !Can("tcp", raddr, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[ssh-tcp] Unauthorized to tcp connect to %s", raddr)
@ -525,14 +525,14 @@ func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr
ResolverChainOption(h.options.Resolver),
)
if err != nil {
log.Logf("[ssh-tcp] %s - %s : %s", h.options.Addr, raddr, err)
log.Logf("[ssh-tcp] %s - %s : %s", h.options.Node.Addr, raddr, err)
return
}
defer conn.Close()
log.Logf("[ssh-tcp] %s <-> %s", h.options.Addr, raddr)
log.Logf("[ssh-tcp] %s <-> %s", h.options.Node.Addr, raddr)
transport(conn, channel)
log.Logf("[ssh-tcp] %s >-< %s", h.options.Addr, raddr)
log.Logf("[ssh-tcp] %s >-< %s", h.options.Node.Addr, raddr)
}
// tcpipForward is structure for RFC 4254 7.1 "tcpip-forward" request