Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
7402fb24
Commit
7402fb24
authored
Jul 22, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add server and listeners
parent
289acfd0
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1109 additions
and
54 deletions
+1109
-54
gost/chain.go
gost/chain.go
+6
-7
gost/cli/cli.go
gost/cli/cli.go
+42
-9
gost/client.go
gost/client.go
+23
-12
gost/gost.go
gost/gost.go
+8
-0
gost/http.go
gost/http.go
+133
-2
gost/server.go
gost/server.go
+116
-6
gost/socks.go
gost/socks.go
+210
-10
gost/srv/cert.pem
gost/srv/cert.pem
+18
-0
gost/srv/key.pem
gost/srv/key.pem
+27
-0
gost/srv/srv.go
gost/srv/srv.go
+111
-0
gost/ss.go
gost/ss.go
+125
-6
gost/tls.go
gost/tls.go
+13
-2
gost/ws.go
gost/ws.go
+277
-0
No files found.
gost/chain.go
View file @
7402fb24
package
gost
import
(
"context"
"net"
)
...
...
@@ -15,18 +14,18 @@ func NewChain(nodes ...Node) *Chain {
}
}
func
(
c
*
Chain
)
Dial
(
ctx
context
.
Context
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
Chain
)
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
if
len
(
c
.
Nodes
)
==
0
{
return
net
.
Dial
(
"tcp"
,
addr
)
}
nodes
:=
c
.
Nodes
conn
,
err
:=
nodes
[
0
]
.
Client
.
Dial
(
ctx
,
nodes
[
0
]
.
Addr
)
conn
,
err
:=
nodes
[
0
]
.
Client
.
Dial
(
nodes
[
0
]
.
Addr
)
if
err
!=
nil
{
return
nil
,
err
}
conn
,
err
=
nodes
[
0
]
.
Client
.
Handshake
(
c
tx
,
c
onn
)
conn
,
err
=
nodes
[
0
]
.
Client
.
Handshake
(
conn
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -37,12 +36,12 @@ func (c *Chain) Dial(ctx context.Context, addr string) (net.Conn, error) {
}
next
:=
nodes
[
i
+
1
]
cc
,
err
:=
node
.
Client
.
Connect
(
c
tx
,
c
onn
,
next
.
Addr
)
cc
,
err
:=
node
.
Client
.
Connect
(
conn
,
next
.
Addr
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
cc
,
err
=
next
.
Client
.
Handshake
(
c
tx
,
c
c
)
cc
,
err
=
next
.
Client
.
Handshake
(
cc
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
...
...
@@ -51,7 +50,7 @@ func (c *Chain) Dial(ctx context.Context, addr string) (net.Conn, error) {
conn
=
cc
}
cc
,
err
:=
nodes
[
len
(
nodes
)
-
1
]
.
Client
.
Connect
(
ctx
,
conn
,
addr
)
cc
,
err
:=
nodes
[
len
(
nodes
)
-
1
]
.
Client
.
Connect
(
conn
,
addr
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
...
...
gost/cli/cli.go
View file @
7402fb24
...
...
@@ -2,11 +2,11 @@ package main
import
(
"bufio"
"context"
"crypto/tls"
"log"
"net/http"
"net/http/httputil"
"net/url"
"github.com/ginuerzh/gost/gost"
...
...
@@ -19,6 +19,30 @@ func init() {
func
main
()
{
chain
:=
gost
.
NewChain
(
/*
// http+ws
gost.Node{
Addr: "127.0.0.1:8000",
Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.WSTransporter("127.0.0.1:8000", nil),
),
},
*/
// http+wss
gost
.
Node
{
Addr
:
"127.0.0.1:8443"
,
Client
:
gost
.
NewClient
(
gost
.
HTTPConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
gost
.
WSSTransporter
(
"127.0.0.1:8443"
,
&
gost
.
WSOptions
{
TLSConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
}},
),
),
},
/*
// http+tcp
gost.Node{
Addr: "127.0.0.1:1080",
Client: gost.NewClient(
...
...
@@ -26,27 +50,36 @@ func main() {
gost.TCPTransporter(),
),
},
*/
/*
// http+tls
gost.Node{
Addr
:
"1
72.24.222.54:8338
"
,
Addr: "1
27.0.0.1:1443
",
Client: gost.NewClient(
gost
.
ShadowConnector
(
url
.
UserPassword
(
"chacha20
"
,
"123456"
)),
gost
.
T
CPTransporter
(
),
gost.
HTTPConnector(url.UserPassword("admin
", "123456")),
gost.T
LSTransporter(&tls.Config{InsecureSkipVerify: true}
),
),
},
*/
/*
// ss+tcp
gost.Node{
Addr
:
"1
72.24.222.54:8080
"
,
Addr: "1
27.0.0.1:8338
",
Client: gost.NewClient(
gost
.
S
OCKS5Connector
(
url
.
UserPassword
(
"cmdsh"
,
"cmdsh
123456"
)),
gost.S
hadowConnector(url.UserPassword("chacha20", "
123456")),
gost.TCPTransporter(),
),
},
*/
)
conn
,
err
:=
chain
.
Dial
(
context
.
Background
(),
"baidu.com:443
"
)
conn
,
err
:=
chain
.
Dial
(
"localhost:10000
"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
conn
=
tls
.
Client
(
conn
,
&
tls
.
Config
{
InsecureSkipVerify
:
true
})
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
"http
s://www.baidu.com
"
,
nil
)
//
conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
"http
://localhost:10000/pkg
"
,
nil
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
...
...
gost/client.go
View file @
7402fb24
package
gost
import
(
"context"
"net"
)
...
...
@@ -10,9 +9,6 @@ type Client struct {
Transporter
Transporter
}
// DefaultClient is a standard HTTP proxy
var
DefaultClient
=
NewClient
(
HTTPConnector
(
nil
),
TCPTransporter
())
func
NewClient
(
c
Connector
,
tr
Transporter
)
*
Client
{
return
&
Client
{
Connector
:
c
,
...
...
@@ -21,25 +17,40 @@ func NewClient(c Connector, tr Transporter) *Client {
}
// Dial connects to the target address
func
(
c
*
Client
)
Dial
(
ctx
context
.
Context
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
Client
)
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
return
net
.
Dial
(
c
.
Transporter
.
Network
(),
addr
)
}
func
(
c
*
Client
)
Handshake
(
ctx
context
.
Context
,
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
c
.
Transporter
.
Handshake
(
ctx
,
conn
)
func
(
c
*
Client
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
c
.
Transporter
.
Handshake
(
conn
)
}
func
(
c
*
Client
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
c
.
Connector
.
Connect
(
conn
,
addr
)
}
// DefaultClient is a standard HTTP proxy client
var
DefaultClient
=
NewClient
(
HTTPConnector
(
nil
),
TCPTransporter
())
func
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
return
DefaultClient
.
Dial
(
addr
)
}
func
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
DefaultClient
.
Handshake
(
conn
)
}
func
(
c
*
Client
)
Connect
(
ctx
context
.
Context
,
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
c
.
Connector
.
Connect
(
ctx
,
conn
,
addr
)
func
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
DefaultClient
.
Connect
(
conn
,
addr
)
}
type
Connector
interface
{
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
}
type
Transporter
interface
{
Network
()
string
Handshake
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
)
(
net
.
Conn
,
error
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
}
type
tcpTransporter
struct
{
...
...
@@ -53,6 +64,6 @@ func (tr *tcpTransporter) Network() string {
return
"tcp"
}
func
(
tr
*
tcpTransporter
)
Handshake
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
func
(
tr
*
tcpTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
}
gost/gost.go
View file @
7402fb24
...
...
@@ -4,8 +4,16 @@ import (
"github.com/go-log/log"
)
const
Version
=
"2.4-dev20170722"
var
Debug
bool
var
(
SmallBufferSize
=
1
*
1024
// 1KB small buffer
MediumBufferSize
=
8
*
1024
// 8KB medium buffer
LargeBufferSize
=
32
*
1024
// 32KB large buffer
)
func
init
()
{
log
.
DefaultLogger
=
&
logger
{}
}
gost/http.go
View file @
7402fb24
...
...
@@ -2,13 +2,13 @@ package gost
import
(
"bufio"
"context"
"encoding/base64"
"fmt"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/go-log/log"
)
...
...
@@ -21,7 +21,7 @@ func HTTPConnector(user *url.Userinfo) Connector {
return
&
httpConnector
{
User
:
user
}
}
func
(
c
*
httpConnector
)
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
httpConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
req
:=
&
http
.
Request
{
Method
:
http
.
MethodConnect
,
URL
:
&
url
.
URL
{
Host
:
addr
},
...
...
@@ -66,3 +66,134 @@ func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, addr string)
return
conn
,
nil
}
type
httpHandler
struct
{
options
*
HandlerOptions
}
func
HTTPHandler
(
opts
...
HandlerOption
)
Handler
{
h
:=
&
httpHandler
{
options
:
&
HandlerOptions
{
Chain
:
new
(
Chain
),
},
}
for
_
,
opt
:=
range
opts
{
opt
(
h
.
options
)
}
return
h
}
func
(
h
*
httpHandler
)
Handle
(
conn
net
.
Conn
)
{
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
if
err
!=
nil
{
log
.
Log
(
"[http]"
,
err
)
return
}
log
.
Logf
(
"[http] %s %s -> %s %s"
,
req
.
Method
,
conn
.
RemoteAddr
(),
req
.
Host
,
req
.
Proto
)
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
log
.
Logf
(
string
(
dump
))
}
if
req
.
Method
==
"PRI"
&&
req
.
ProtoMajor
==
2
{
log
.
Logf
(
"[http] %s <- %s : Not an HTTP2 server"
,
conn
.
RemoteAddr
(),
req
.
Host
)
resp
:=
"HTTP/1.1 400 Bad Request
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
conn
.
Write
([]
byte
(
resp
))
return
}
valid
:=
false
u
,
p
,
_
:=
h
.
basicProxyAuth
(
req
.
Header
.
Get
(
"Proxy-Authorization"
))
users
:=
h
.
options
.
Users
for
_
,
user
:=
range
users
{
username
:=
user
.
Username
()
password
,
_
:=
user
.
Password
()
if
(
u
==
username
&&
p
==
password
)
||
(
u
==
username
&&
password
==
""
)
||
(
username
==
""
&&
p
==
password
)
{
valid
=
true
break
}
}
if
len
(
users
)
>
0
&&
!
valid
{
log
.
Logf
(
"[http] %s <- %s : proxy authentication required"
,
conn
.
RemoteAddr
(),
req
.
Host
)
resp
:=
"HTTP/1.1 407 Proxy Authentication Required
\r\n
"
+
"Proxy-Authenticate: Basic realm=
\"
gost
\"\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
conn
.
Write
([]
byte
(
resp
))
return
}
req
.
Header
.
Del
(
"Proxy-Authorization"
)
// forward http request
//lastNode := s.Base.Chain.lastNode
//if lastNode != nil && lastNode.Transport == "" && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
// s.forwardRequest(req)
// return
//}
// if !s.Base.Node.Can("tcp", req.Host) {
// glog.Errorf("Unauthorized to tcp connect to %s", req.Host)
// return
// }
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
req
.
Host
)
if
err
!=
nil
{
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
err
)
b
:=
[]
byte
(
"HTTP/1.1 503 Service unavailable
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
if
Debug
{
log
.
Logf
(
"[http] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
string
(
b
))
}
conn
.
Write
(
b
)
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
(),
req
.
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
(),
req
.
Host
,
err
)
return
}
}
log
.
Logf
(
"[http] %s <-> %s"
,
conn
.
RemoteAddr
(),
req
.
Host
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[http] %s >-< %s"
,
conn
.
RemoteAddr
(),
req
.
Host
)
}
func
(
h
*
httpHandler
)
basicProxyAuth
(
proxyAuth
string
)
(
username
,
password
string
,
ok
bool
)
{
if
proxyAuth
==
""
{
return
}
if
!
strings
.
HasPrefix
(
proxyAuth
,
"Basic "
)
{
return
}
c
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
strings
.
TrimPrefix
(
proxyAuth
,
"Basic "
))
if
err
!=
nil
{
return
}
cs
:=
string
(
c
)
s
:=
strings
.
IndexByte
(
cs
,
':'
)
if
s
<
0
{
return
}
return
cs
[
:
s
],
cs
[
s
+
1
:
],
true
}
gost/server.go
View file @
7402fb24
...
...
@@ -2,17 +2,127 @@ package gost
import
(
"crypto/tls"
"io"
"net"
"time"
"net/url"
"github.com/go-log/log"
)
type
Server
struct
{
Addr
string
`opt:"addr"`
// [host]:port
Protocol
string
`opt:"protocol"`
// protocol: http/socks5/ss
TLSConfig
*
tls
.
Config
l
net
.
Listener
handler
Handler
}
func
(
s
*
Server
)
Handle
(
h
Handler
)
{
s
.
handler
=
h
}
func
(
s
*
Server
)
Serve
(
l
net
.
Listener
)
error
{
defer
l
.
Close
()
var
tempDelay
time
.
Duration
for
{
conn
,
e
:=
l
.
Accept
()
if
e
!=
nil
{
if
ne
,
ok
:=
e
.
(
net
.
Error
);
ok
&&
ne
.
Temporary
()
{
if
tempDelay
==
0
{
tempDelay
=
5
*
time
.
Millisecond
}
else
{
tempDelay
*=
2
}
if
max
:=
1
*
time
.
Second
;
tempDelay
>
max
{
tempDelay
=
max
}
log
.
Logf
(
"server: Accept error: %v; retrying in %v"
,
e
,
tempDelay
)
time
.
Sleep
(
tempDelay
)
continue
}
return
e
}
tempDelay
=
0
go
s
.
handler
.
Handle
(
conn
)
}
}
type
Listener
interface
{
net
.
Listener
}
type
tcpListener
struct
{
net
.
Listener
}
func
TCPListener
(
addr
string
)
(
Listener
,
error
)
{
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
tcpListener
{
Listener
:
&
tcpKeepAliveListener
{
ln
.
(
*
net
.
TCPListener
)}},
nil
}
type
Handler
interface
{
Handle
(
net
.
Conn
)
}
type
HandlerOptions
struct
{
Chain
*
Chain
Users
[]
url
.
Userinfo
`opt:"user"`
// authentication for proxy
Users
[]
*
url
.
Userinfo
TLSConfig
*
tls
.
Config
}
type
HandlerOption
func
(
opts
*
HandlerOptions
)
func
ChainHandlerOption
(
chain
*
Chain
)
HandlerOption
{
return
func
(
opts
*
HandlerOptions
)
{
opts
.
Chain
=
chain
}
}
func
UsersHandlerOption
(
users
...*
url
.
Userinfo
)
HandlerOption
{
return
func
(
opts
*
HandlerOptions
)
{
opts
.
Users
=
users
}
}
func
TLSConfigHandlerOption
(
config
*
tls
.
Config
)
HandlerOption
{
return
func
(
opts
*
HandlerOptions
)
{
opts
.
TLSConfig
=
config
}
}
func
transport
(
rw1
,
rw2
io
.
ReadWriter
)
error
{
errc
:=
make
(
chan
error
,
1
)
go
func
()
{
_
,
err
:=
io
.
Copy
(
rw1
,
rw2
)
errc
<-
err
}()
go
func
()
{
_
,
err
:=
io
.
Copy
(
rw2
,
rw1
)
errc
<-
err
}()
return
<-
errc
}
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type
tcpKeepAliveListener
struct
{
*
net
.
TCPListener
}
func
(
s
*
Server
)
Run
()
error
{
return
nil
func
(
ln
tcpKeepAliveListener
)
Accept
()
(
c
net
.
Conn
,
err
error
)
{
tc
,
err
:=
ln
.
AcceptTCP
()
if
err
!=
nil
{
return
}
tc
.
SetKeepAlive
(
true
)
tc
.
SetKeepAlivePeriod
(
3
*
time
.
Minute
)
return
tc
,
nil
}
gost/socks.go
View file @
7402fb24
package
gost
import
(
"context"
"crypto/tls"
"errors"
"fmt"
...
...
@@ -23,25 +22,25 @@ const (
CmdUdpTun
uint8
=
0xF3
// extended method for udp over tcp
)
type
C
lientSelector
struct
{
type
c
lientSelector
struct
{
methods
[]
uint8
User
*
url
.
Userinfo
TLSConfig
*
tls
.
Config
}
func
(
selector
*
C
lientSelector
)
Methods
()
[]
uint8
{
func
(
selector
*
c
lientSelector
)
Methods
()
[]
uint8
{
return
selector
.
methods
}
func
(
selector
*
C
lientSelector
)
AddMethod
(
methods
...
uint8
)
{
func
(
selector
*
c
lientSelector
)
AddMethod
(
methods
...
uint8
)
{
selector
.
methods
=
append
(
selector
.
methods
,
methods
...
)
}
func
(
selector
*
C
lientSelector
)
Select
(
methods
...
uint8
)
(
method
uint8
)
{
func
(
selector
*
c
lientSelector
)
Select
(
methods
...
uint8
)
(
method
uint8
)
{
return
}
func
(
selector
*
C
lientSelector
)
OnSelected
(
method
uint8
,
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
func
(
selector
*
c
lientSelector
)
OnSelected
(
method
uint8
,
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
switch
method
{
case
MethodTLS
:
conn
=
tls
.
Client
(
conn
,
selector
.
TLSConfig
)
...
...
@@ -83,6 +82,105 @@ func (selector *ClientSelector) OnSelected(method uint8, conn net.Conn) (net.Con
return
conn
,
nil
}
type
serverSelector
struct
{
methods
[]
uint8
Users
[]
*
url
.
Userinfo
TLSConfig
*
tls
.
Config
}
func
(
selector
*
serverSelector
)
Methods
()
[]
uint8
{
return
selector
.
methods
}
func
(
selector
*
serverSelector
)
AddMethod
(
methods
...
uint8
)
{
selector
.
methods
=
append
(
selector
.
methods
,
methods
...
)
}
func
(
selector
*
serverSelector
)
Select
(
methods
...
uint8
)
(
method
uint8
)
{
if
Debug
{
log
.
Logf
(
"[socks5] %d %d %v"
,
gosocks5
.
Ver5
,
len
(
methods
),
methods
)
}
method
=
gosocks5
.
MethodNoAuth
for
_
,
m
:=
range
methods
{
if
m
==
MethodTLS
{
method
=
m
break
}
}
// when user/pass is set, auth is mandatory
if
len
(
selector
.
Users
)
>
0
{
if
method
==
gosocks5
.
MethodNoAuth
{
method
=
gosocks5
.
MethodUserPass
}
if
method
==
MethodTLS
{
method
=
MethodTLSAuth
}
}
return
}
func
(
selector
*
serverSelector
)
OnSelected
(
method
uint8
,
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
if
Debug
{
log
.
Logf
(
"[socks5] %d %d"
,
gosocks5
.
Ver5
,
method
)
}
switch
method
{
case
MethodTLS
:
conn
=
tls
.
Server
(
conn
,
selector
.
TLSConfig
)
case
gosocks5
.
MethodUserPass
,
MethodTLSAuth
:
if
method
==
MethodTLSAuth
{
conn
=
tls
.
Server
(
conn
,
selector
.
TLSConfig
)
}
req
,
err
:=
gosocks5
.
ReadUserPassRequest
(
conn
)
if
err
!=
nil
{
log
.
Log
(
"[socks5]"
,
err
)
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5]"
,
req
.
String
())
}
valid
:=
false
for
_
,
user
:=
range
selector
.
Users
{
username
:=
user
.
Username
()
password
,
_
:=
user
.
Password
()
if
(
req
.
Username
==
username
&&
req
.
Password
==
password
)
||
(
req
.
Username
==
username
&&
password
==
""
)
||
(
username
==
""
&&
req
.
Password
==
password
)
{
valid
=
true
break
}
}
if
len
(
selector
.
Users
)
>
0
&&
!
valid
{
resp
:=
gosocks5
.
NewUserPassResponse
(
gosocks5
.
UserPassVer
,
gosocks5
.
Failure
)
if
err
:=
resp
.
Write
(
conn
);
err
!=
nil
{
log
.
Log
(
"[socks5]"
,
err
)
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5]"
,
resp
)
}
log
.
Log
(
"[socks5] proxy authentication required"
)
return
nil
,
gosocks5
.
ErrAuthFailure
}
resp
:=
gosocks5
.
NewUserPassResponse
(
gosocks5
.
UserPassVer
,
gosocks5
.
Succeeded
)
if
err
:=
resp
.
Write
(
conn
);
err
!=
nil
{
log
.
Log
(
"[socks5]"
,
err
)
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5]"
,
resp
)
}
case
gosocks5
.
MethodNoAcceptable
:
return
nil
,
gosocks5
.
ErrBadMethod
}
return
conn
,
nil
}
type
socks5Connector
struct
{
User
*
url
.
Userinfo
}
...
...
@@ -91,8 +189,8 @@ func SOCKS5Connector(user *url.Userinfo) Connector {
return
&
socks5Connector
{
User
:
user
}
}
func
(
c
*
socks5Connector
)
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
selector
:=
&
C
lientSelector
{
func
(
c
*
socks5Connector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
selector
:=
&
c
lientSelector
{
TLSConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
User
:
c
.
User
,
}
...
...
@@ -148,7 +246,7 @@ func SOCKS4Connector() Connector {
return
&
socks4Connector
{}
}
func
(
c
*
socks4Connector
)
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
socks4Connector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
taddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp4"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -191,7 +289,7 @@ func SOCKS4AConnector() Connector {
return
&
socks4aConnector
{}
}
func
(
c
*
socks4aConnector
)
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
socks4aConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
host
,
port
,
err
:=
net
.
SplitHostPort
(
addr
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -223,3 +321,105 @@ func (c *socks4aConnector) Connect(ctx context.Context, conn net.Conn, addr stri
return
conn
,
nil
}
type
socks5Handler
struct
{
selector
*
serverSelector
options
*
HandlerOptions
}
func
SOCKS5Handler
(
opts
...
HandlerOption
)
Handler
{
options
:=
&
HandlerOptions
{
Chain
:
new
(
Chain
),
}
for
_
,
opt
:=
range
opts
{
opt
(
options
)
}
selector
:=
&
serverSelector
{
// socks5 server selector
Users
:
options
.
Users
,
TLSConfig
:
options
.
TLSConfig
,
}
// methods that socks5 server supported
selector
.
AddMethod
(
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
,
MethodTLS
,
MethodTLSAuth
,
)
return
&
socks5Handler
{
options
:
options
,
selector
:
selector
,
}
}
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
)
return
}
if
Debug
{
log
.
Logf
(
"[socks5] %s -> %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
req
)
}
switch
req
.
Cmd
{
case
gosocks5
.
CmdConnect
:
log
.
Logf
(
"[socks5-connect] %s -> %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
h
.
handleConnect
(
conn
,
req
)
case
gosocks5
.
CmdBind
:
log
.
Logf
(
"[socks5-bind] %s - %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
h
.
handleBind
(
conn
,
req
)
case
gosocks5
.
CmdUdp
:
log
.
Logf
(
"[socks5-udp] %s - %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
//s.handleUDPRelay(req)
case
CmdUdpTun
:
log
.
Logf
(
"[socks5-rudp] %s - %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
//s.handleUDPTunnel(req)
default
:
log
.
Log
(
"[socks5] Unrecognized request:"
,
req
.
Cmd
)
}
}
func
(
h
*
socks5Handler
)
handleConnect
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
addr
:=
req
.
Addr
.
String
()
//! if !s.Base.Node.Can("tcp", addr) {
//! glog.Errorf("Unauthorized to tcp connect to %s", addr)
//! rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
//! rep.Write(s.conn)
//! return
//! }
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
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
)
}
return
}
defer
cc
.
Close
()
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
)
return
}
if
Debug
{
log
.
Logf
(
"[socks5-connect] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
rep
)
}
log
.
Logf
(
"[socks5-connect] %s <-> %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[socks5-connect] %s >-< %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
)
}
func
(
h
*
socks5Handler
)
handleBind
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
// TODO: socks5 bind
}
gost/srv/cert.pem
0 → 100644
View file @
7402fb24
-----BEGIN CERTIFICATE-----
MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
-----END CERTIFICATE-----
gost/srv/key.pem
0 → 100644
View file @
7402fb24
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
-----END RSA PRIVATE KEY-----
gost/srv/srv.go
0 → 100644
View file @
7402fb24
package
main
import
(
"crypto/tls"
"log"
"net/url"
"sync"
"github.com/ginuerzh/gost/gost"
)
func
init
()
{
log
.
SetFlags
(
log
.
LstdFlags
|
log
.
Lshortfile
)
gost
.
Debug
=
true
}
func
main
()
{
wg
:=
sync
.
WaitGroup
{}
wg
.
Add
(
1
)
go
httpServer
(
&
wg
)
wg
.
Add
(
1
)
go
tlsServer
(
&
wg
)
wg
.
Add
(
1
)
go
shadowServer
(
&
wg
)
wg
.
Add
(
1
)
go
wsServer
(
&
wg
)
wg
.
Add
(
1
)
go
wssServer
(
&
wg
)
wg
.
Wait
()
}
func
httpServer
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
HTTPHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
))
ln
,
err
:=
gost
.
TCPListener
(
":1080"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
tlsServer
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
HTTPHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
))
cert
,
err
:=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
ln
,
err
:=
gost
.
TLSListener
(
":1443"
,
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}})
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
wsServer
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
HTTPHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
))
ln
,
err
:=
gost
.
WSListener
(
":8000"
,
nil
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
wssServer
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
HTTPHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
))
cert
,
err
:=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
ln
,
err
:=
gost
.
WSSListener
(
":8443"
,
&
gost
.
WSOptions
{
TLSConfig
:
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}})
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
shadowServer
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
ShadowHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"chacha20"
,
"123456"
)),
))
ln
,
err
:=
gost
.
TCPListener
(
":8338"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
gost/ss.go
View file @
7402fb24
package
gost
import
(
"context"
"encoding/binary"
"fmt"
"io"
"net"
"net/url"
"strconv"
"time"
"github.com/go-log/log"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
...
...
@@ -15,10 +19,6 @@ type shadowConn struct {
conn
net
.
Conn
}
func
ShadowConn
(
conn
net
.
Conn
)
net
.
Conn
{
return
&
shadowConn
{
conn
:
conn
}
}
func
(
c
*
shadowConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
c
.
conn
.
Read
(
b
)
}
...
...
@@ -61,7 +61,7 @@ func ShadowConnector(cipher *url.Userinfo) Connector {
return
&
shadowConnector
{
Cipher
:
cipher
}
}
func
(
c
*
shadowConnector
)
Connect
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
shadowConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
rawaddr
,
err
:=
ss
.
RawAddr
(
addr
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -84,3 +84,122 @@ func (c *shadowConnector) Connect(ctx context.Context, conn net.Conn, addr strin
}
return
&
shadowConn
{
conn
:
sc
},
nil
}
type
shadowHandler
struct
{
options
*
HandlerOptions
}
func
ShadowHandler
(
opts
...
HandlerOption
)
Handler
{
h
:=
&
shadowHandler
{
options
:
&
HandlerOptions
{
Chain
:
new
(
Chain
),
},
}
for
_
,
opt
:=
range
opts
{
opt
(
h
.
options
)
}
return
h
}
func
(
h
*
shadowHandler
)
Handle
(
conn
net
.
Conn
)
{
var
method
,
password
string
users
:=
h
.
options
.
Users
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
log
.
Log
(
"[ss]"
,
err
)
return
}
conn
=
&
shadowConn
{
conn
:
ss
.
NewConn
(
conn
,
cipher
)}
log
.
Logf
(
"[ss] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
addr
,
err
:=
h
.
getRequest
(
conn
)
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
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
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[ss] %s >-< %s"
,
conn
.
RemoteAddr
(),
addr
)
}
const
(
idType
=
0
// address type index
idIP0
=
1
// ip addres start index
idDmLen
=
1
// domain address length index
idDm0
=
2
// domain address start index
typeIPv4
=
1
// type is ipv4 address
typeDm
=
3
// type is domain address
typeIPv6
=
4
// type is ipv6 address
lenIPv4
=
net
.
IPv4len
+
2
// ipv4 + 2port
lenIPv6
=
net
.
IPv6len
+
2
// ipv6 + 2port
lenDmBase
=
2
// 1addrLen + 2port, plus addrLen
lenHmacSha1
=
10
)
// This function is copied from shadowsocks library with some modification.
func
(
h
*
shadowHandler
)
getRequest
(
conn
net
.
Conn
)
(
host
string
,
err
error
)
{
// buf size should at least have the same size with the largest possible
// request size (when addrType is 3, domain name has at most 256 bytes)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
buf
:=
make
([]
byte
,
SmallBufferSize
)
// read till we get possible domain length field
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
30
*
time
.
Second
))
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
return
}
var
reqStart
,
reqEnd
int
addrType
:=
buf
[
idType
]
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv4
case
typeIPv6
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
case
typeDm
:
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
return
}
reqStart
,
reqEnd
=
idDm0
,
int
(
idDm0
+
buf
[
idDmLen
]
+
lenDmBase
)
default
:
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
addrType
&
ss
.
AddrMask
)
return
}
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
return
}
// Return string for typeIP is not most efficient, but browsers (Chrome,
// Safari, Firefox) all seems using typeDm exclusively. So this is not a
// big problem.
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv4len
])
.
String
()
case
typeIPv6
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv6len
])
.
String
()
case
typeDm
:
host
=
string
(
buf
[
idDm0
:
idDm0
+
buf
[
idDmLen
]])
}
// parse port
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
host
=
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
int
(
port
)))
return
}
gost/tls.go
View file @
7402fb24
package
gost
import
(
"context"
"crypto/tls"
"net"
)
...
...
@@ -18,6 +17,18 @@ func (tr *tlsTransporter) Network() string {
return
"tcp"
}
func
(
tr
*
tlsTransporter
)
Handshake
(
c
tx
context
.
Context
,
c
onn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
func
(
tr
*
tlsTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
tls
.
Client
(
conn
,
tr
.
TLSClientConfig
),
nil
}
type
tlsListener
struct
{
net
.
Listener
}
func
TLSListener
(
addr
string
,
config
*
tls
.
Config
)
(
Listener
,
error
)
{
ln
,
err
:=
tls
.
Listen
(
"tcp"
,
addr
,
config
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
tlsListener
{
Listener
:
ln
},
nil
}
gost/ws.go
0 → 100644
View file @
7402fb24
package
gost
import
(
"crypto/tls"
"net"
"net/http"
"net/http/httputil"
"time"
"net/url"
"github.com/go-log/log"
"gopkg.in/gorilla/websocket.v1"
)
type
WSOptions
struct
{
ReadBufferSize
int
WriteBufferSize
int
HandshakeTimeout
time
.
Duration
EnableCompression
bool
TLSConfig
*
tls
.
Config
}
type
websocketConn
struct
{
conn
*
websocket
.
Conn
rb
[]
byte
}
func
websocketClientConn
(
url
string
,
conn
net
.
Conn
,
options
*
WSOptions
)
(
net
.
Conn
,
error
)
{
if
options
==
nil
{
options
=
&
WSOptions
{}
}
dialer
:=
websocket
.
Dialer
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
TLSClientConfig
:
options
.
TLSConfig
,
HandshakeTimeout
:
options
.
HandshakeTimeout
,
EnableCompression
:
options
.
EnableCompression
,
NetDial
:
func
(
net
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
},
}
c
,
resp
,
err
:=
dialer
.
Dial
(
url
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
resp
.
Body
.
Close
()
return
&
websocketConn
{
conn
:
c
},
nil
}
func
websocketServerConn
(
conn
*
websocket
.
Conn
)
net
.
Conn
{
// conn.EnableWriteCompression(true)
return
&
websocketConn
{
conn
:
conn
,
}
}
func
(
c
*
websocketConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
if
len
(
c
.
rb
)
==
0
{
_
,
c
.
rb
,
err
=
c
.
conn
.
ReadMessage
()
}
n
=
copy
(
b
,
c
.
rb
)
c
.
rb
=
c
.
rb
[
n
:
]
return
}
func
(
c
*
websocketConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
err
=
c
.
conn
.
WriteMessage
(
websocket
.
BinaryMessage
,
b
)
n
=
len
(
b
)
return
}
func
(
c
*
websocketConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
func
(
c
*
websocketConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
conn
.
LocalAddr
()
}
func
(
c
*
websocketConn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
conn
.
RemoteAddr
()
}
func
(
conn
*
websocketConn
)
SetDeadline
(
t
time
.
Time
)
error
{
if
err
:=
conn
.
SetReadDeadline
(
t
);
err
!=
nil
{
return
err
}
return
conn
.
SetWriteDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
wsTransporter
struct
{
addr
string
options
*
WSOptions
}
func
WSTransporter
(
addr
string
,
opts
*
WSOptions
)
Transporter
{
return
&
wsTransporter
{
addr
:
addr
,
options
:
opts
,
}
}
func
(
tr
*
wsTransporter
)
Network
()
string
{
return
"tcp"
}
func
(
tr
*
wsTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
url
:=
url
.
URL
{
Scheme
:
"ws"
,
Host
:
tr
.
addr
,
Path
:
"/ws"
}
return
websocketClientConn
(
url
.
String
(),
conn
,
tr
.
options
)
}
type
wssTransporter
struct
{
addr
string
options
*
WSOptions
}
func
WSSTransporter
(
addr
string
,
opts
*
WSOptions
)
Transporter
{
return
&
wssTransporter
{
addr
:
addr
,
options
:
opts
,
}
}
func
(
tr
*
wssTransporter
)
Network
()
string
{
return
"tcp"
}
func
(
tr
*
wssTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
url
:=
url
.
URL
{
Scheme
:
"wss"
,
Host
:
tr
.
addr
,
Path
:
"/ws"
}
return
websocketClientConn
(
url
.
String
(),
conn
,
tr
.
options
)
}
type
wsListener
struct
{
addr
net
.
Addr
upgrader
*
websocket
.
Upgrader
srv
*
http
.
Server
connChan
chan
net
.
Conn
errChan
chan
error
}
func
WSListener
(
addr
string
,
options
*
WSOptions
)
(
Listener
,
error
)
{
tcpAddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
if
options
==
nil
{
options
=
&
WSOptions
{}
}
l
:=
&
wsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
CheckOrigin
:
func
(
r
*
http
.
Request
)
bool
{
return
true
},
EnableCompression
:
options
.
EnableCompression
,
},
connChan
:
make
(
chan
net
.
Conn
,
32
),
errChan
:
make
(
chan
error
,
1
),
}
mux
:=
http
.
NewServeMux
()
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
mux
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
if
err
!=
nil
{
return
nil
,
err
}
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tcpKeepAliveListener
{
ln
})
if
err
!=
nil
{
l
.
errChan
<-
err
}
close
(
l
.
errChan
)
}()
select
{
case
err
:=
<-
l
.
errChan
:
return
nil
,
err
default
:
}
return
l
,
nil
}
func
(
l
*
wsListener
)
upgrade
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
log
.
Logf
(
"[ws] %s -> %s"
,
r
.
RemoteAddr
,
l
.
addr
)
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
r
,
false
)
log
.
Log
(
string
(
dump
))
}
conn
,
err
:=
l
.
upgrader
.
Upgrade
(
w
,
r
,
nil
)
if
err
!=
nil
{
log
.
Logf
(
"[ws] %s - %s : %s"
,
r
.
RemoteAddr
,
l
.
addr
,
err
)
return
}
l
.
connChan
<-
websocketServerConn
(
conn
)
}
func
(
l
*
wsListener
)
Accept
()
(
conn
net
.
Conn
,
err
error
)
{
select
{
case
conn
=
<-
l
.
connChan
:
case
err
=
<-
l
.
errChan
:
}
return
}
func
(
l
*
wsListener
)
Close
()
error
{
return
l
.
srv
.
Close
()
}
func
(
l
*
wsListener
)
Addr
()
net
.
Addr
{
return
l
.
addr
}
type
wssListener
struct
{
*
wsListener
}
func
WSSListener
(
addr
string
,
options
*
WSOptions
)
(
Listener
,
error
)
{
tcpAddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
if
options
==
nil
{
options
=
&
WSOptions
{}
}
l
:=
&
wssListener
{
wsListener
:
&
wsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
CheckOrigin
:
func
(
r
*
http
.
Request
)
bool
{
return
true
},
EnableCompression
:
options
.
EnableCompression
,
},
connChan
:
make
(
chan
net
.
Conn
,
32
),
errChan
:
make
(
chan
error
,
1
),
},
}
mux
:=
http
.
NewServeMux
()
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
TLSConfig
:
options
.
TLSConfig
,
Handler
:
mux
,
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
if
err
!=
nil
{
return
nil
,
err
}
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
},
options
.
TLSConfig
))
if
err
!=
nil
{
l
.
errChan
<-
err
}
close
(
l
.
errChan
)
}()
select
{
case
err
:=
<-
l
.
errChan
:
return
nil
,
err
default
:
}
return
l
,
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment