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
97d2de15
Commit
97d2de15
authored
Aug 03, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add whitelist/blacklist support
parent
c02bc32c
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
386 additions
and
214 deletions
+386
-214
gost/cmd/gost/main.go
gost/cmd/gost/main.go
+55
-2
gost/cmd/gost/parser.go
gost/cmd/gost/parser.go
+0
-139
gost/examples/bench/cli.go
gost/examples/bench/cli.go
+2
-2
gost/examples/bench/srv.go
gost/examples/bench/srv.go
+13
-0
gost/gost.go
gost/gost.go
+60
-2
gost/handler.go
gost/handler.go
+16
-0
gost/http.go
gost/http.go
+11
-5
gost/http2.go
gost/http2.go
+5
-4
gost/log.go
gost/log.go
+1
-1
gost/node.go
gost/node.go
+156
-6
gost/permissions.go
gost/permissions.go
+8
-8
gost/socks.go
gost/socks.go
+38
-32
gost/ss.go
gost/ss.go
+5
-1
gost/ssh.go
gost/ssh.go
+15
-11
gost/tls.go
gost/tls.go
+1
-1
No files found.
gost/cmd/gost/main.go
View file @
97d2de15
...
@@ -46,6 +46,8 @@ func init() {
...
@@ -46,6 +46,8 @@ func init() {
fmt
.
Fprintf
(
os
.
Stderr
,
"gost %s (%s)
\n
"
,
gost
.
Version
,
runtime
.
Version
())
fmt
.
Fprintf
(
os
.
Stderr
,
"gost %s (%s)
\n
"
,
gost
.
Version
,
runtime
.
Version
())
os
.
Exit
(
0
)
os
.
Exit
(
0
)
}
}
gost
.
Debug
=
options
.
debugMode
}
}
func
main
()
{
func
main
()
{
...
@@ -54,8 +56,8 @@ func main() {
...
@@ -54,8 +56,8 @@ func main() {
func
buildChain
()
(
*
gost
.
Chain
,
error
)
{
func
buildChain
()
(
*
gost
.
Chain
,
error
)
{
chain
:=
gost
.
NewChain
()
chain
:=
gost
.
NewChain
()
for
_
,
cn
:=
range
options
.
chainNodes
{
for
_
,
ns
:=
range
options
.
chainNodes
{
node
,
err
:=
parseNode
(
cn
)
node
,
err
:=
gost
.
ParseNode
(
ns
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -66,9 +68,60 @@ func buildChain() (*gost.Chain, error) {
...
@@ -66,9 +68,60 @@ func buildChain() (*gost.Chain, error) {
tr
=
gost
.
TLSTransporter
()
tr
=
gost
.
TLSTransporter
()
case
"ws"
:
case
"ws"
:
tr
=
gost
.
WSTransporter
(
nil
)
tr
=
gost
.
WSTransporter
(
nil
)
case
"wss"
:
tr
=
gost
.
WSSTransporter
(
nil
)
case
"kcp"
:
if
!
chain
.
IsEmpty
()
{
log
.
Log
(
"KCP must be the first node in the proxy chain"
)
return
nil
,
err
}
tr
=
gost
.
KCPTransporter
(
nil
)
case
"ssh"
:
if
node
.
Protocol
==
"direct"
||
node
.
Protocol
==
"remote"
{
tr
=
gost
.
SSHForwardTransporter
()
}
else
{
tr
=
gost
.
SSHTunnelTransporter
()
}
case
"quic"
:
if
!
chain
.
IsEmpty
()
{
log
.
Log
(
"QUIC must be the first node in the proxy chain"
)
return
nil
,
err
}
tr
=
gost
.
QUICTransporter
(
nil
)
case
"http2"
:
tr
=
gost
.
HTTP2Transporter
(
nil
)
case
"h2"
:
tr
=
gost
.
H2Transporter
(
nil
)
case
"h2c"
:
tr
=
gost
.
H2CTransporter
()
default
:
tr
=
gost
.
TCPTransporter
()
}
}
var
connector
gost
.
Connector
var
connector
gost
.
Connector
switch
node
.
Protocol
{
case
"http2"
:
connector
=
gost
.
HTTP2Connector
(
nil
)
case
"socks"
,
"socks5"
:
connector
=
gost
.
SOCKS5Connector
(
nil
)
case
"socks4"
:
connector
=
gost
.
SOCKS4Connector
()
case
"socks4a"
:
connector
=
gost
.
SOCKS4AConnector
()
case
"ss"
:
connector
=
gost
.
ShadowConnector
(
nil
)
case
"http"
:
fallthrough
default
:
node
.
Protocol
=
"http"
// default protocol is HTTP
connector
=
gost
.
HTTPConnector
(
nil
)
}
node
.
Client
=
&
gost
.
Client
{
Connector
:
connector
,
Transporter
:
tr
,
}
chain
.
AddNode
(
node
)
}
}
return
chain
,
nil
return
chain
,
nil
...
...
gost/cmd/gost/parser.go
deleted
100644 → 0
View file @
c02bc32c
package
main
import
(
"bufio"
"net"
"net/url"
"os"
"strings"
"github.com/ginuerzh/gost/gost"
"github.com/go-log/log"
)
type
node
struct
{
Addr
string
Protocol
string
// protocol: http/socks5/ss
Transport
string
// transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
Remote
string
// remote address, used by tcp/udp port forwarding
Users
[]
*
url
.
Userinfo
// authentication for proxy
Whitelist
*
gost
.
Permissions
Blacklist
*
gost
.
Permissions
values
url
.
Values
serverName
string
}
func
parseNode
(
s
string
)
(
n
node
,
err
error
)
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
s
=
"gost://"
+
s
}
u
,
err
:=
url
.
Parse
(
s
)
if
err
!=
nil
{
return
}
query
:=
u
.
Query
()
n
=
node
{
Addr
:
u
.
Host
,
}
if
query
.
Get
(
"whitelist"
)
!=
""
{
if
n
.
Whitelist
,
err
=
gost
.
ParsePermissions
(
query
.
Get
(
"whitelist"
));
err
!=
nil
{
return
}
}
else
{
// By default allow for everyting
n
.
Whitelist
,
_
=
gost
.
ParsePermissions
(
"*:*:*"
)
}
if
query
.
Get
(
"blacklist"
)
!=
""
{
if
n
.
Blacklist
,
err
=
gost
.
ParsePermissions
(
query
.
Get
(
"blacklist"
));
err
!=
nil
{
return
}
}
else
{
// By default block nothing
n
.
Blacklist
,
_
=
gost
.
ParsePermissions
(
""
)
}
if
u
.
User
!=
nil
{
n
.
Users
=
append
(
n
.
Users
,
u
.
User
)
}
users
,
er
:=
parseUsers
(
n
.
values
.
Get
(
"secrets"
))
if
users
!=
nil
{
n
.
Users
=
append
(
n
.
Users
,
users
...
)
}
if
er
!=
nil
{
log
.
Log
(
"load secrets:"
,
er
)
}
if
strings
.
Contains
(
u
.
Host
,
":"
)
{
n
.
serverName
,
_
,
_
=
net
.
SplitHostPort
(
u
.
Host
)
if
n
.
serverName
==
""
{
n
.
serverName
=
"localhost"
// default server name
}
}
schemes
:=
strings
.
Split
(
u
.
Scheme
,
"+"
)
if
len
(
schemes
)
==
1
{
n
.
Protocol
=
schemes
[
0
]
n
.
Transport
=
schemes
[
0
]
}
if
len
(
schemes
)
==
2
{
n
.
Protocol
=
schemes
[
0
]
n
.
Transport
=
schemes
[
1
]
}
switch
n
.
Transport
{
case
"ws"
,
"wss"
,
"tls"
,
"h2"
,
"h2c"
,
"quic"
,
"kcp"
,
"redirect"
,
"ssu"
,
"ssh"
:
case
"https"
:
n
.
Protocol
=
"http"
n
.
Transport
=
"tls"
case
"http2"
:
// http2 -> http2+tls, h2c mode is http2+tcp
n
.
Protocol
=
"http2"
n
.
Transport
=
"tls"
case
"tcp"
,
"udp"
:
// started from v2.1, tcp and udp are for local port forwarding
n
.
Remote
=
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
)
case
"rtcp"
,
"rudp"
:
// rtcp and rudp are for remote port forwarding
n
.
Remote
=
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
)
default
:
n
.
Transport
=
""
}
switch
n
.
Protocol
{
case
"http"
,
"http2"
,
"socks"
,
"socks4"
,
"socks4a"
,
"socks5"
,
"ss"
:
default
:
n
.
Protocol
=
""
}
return
}
func
parseUsers
(
s
string
)
(
users
[]
*
url
.
Userinfo
,
err
error
)
{
if
s
==
""
{
return
}
f
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
return
}
scanner
:=
bufio
.
NewScanner
(
f
)
for
scanner
.
Scan
()
{
line
:=
strings
.
TrimSpace
(
scanner
.
Text
())
if
line
==
""
||
strings
.
HasPrefix
(
line
,
"#"
)
{
continue
}
s
:=
strings
.
SplitN
(
line
,
" "
,
2
)
if
len
(
s
)
==
1
{
users
=
append
(
users
,
url
.
User
(
strings
.
TrimSpace
(
s
[
0
])))
}
else
if
len
(
s
)
==
2
{
users
=
append
(
users
,
url
.
UserPassword
(
strings
.
TrimSpace
(
s
[
0
]),
strings
.
TrimSpace
(
s
[
1
])))
}
}
err
=
scanner
.
Err
()
return
}
gost/examples/bench/cli.go
View file @
97d2de15
...
@@ -188,14 +188,14 @@ func request(chain *gost.Chain, start <-chan struct{}) {
...
@@ -188,14 +188,14 @@ func request(chain *gost.Chain, start <-chan struct{}) {
swg
.
Done
()
swg
.
Done
()
<-
start
<-
start
conn
,
err
:=
chain
.
Dial
(
"localhost:1
0000
"
)
conn
,
err
:=
chain
.
Dial
(
"localhost:1
8888
"
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
return
return
}
}
defer
conn
.
Close
()
defer
conn
.
Close
()
//conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
//conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
"http://localhost:1
0000/pkg
"
,
nil
)
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
"http://localhost:1
8888
"
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
return
return
...
...
gost/examples/bench/srv.go
View file @
97d2de15
...
@@ -3,7 +3,9 @@ package main
...
@@ -3,7 +3,9 @@ package main
import
(
import
(
"crypto/tls"
"crypto/tls"
"flag"
"flag"
"fmt"
"log"
"log"
"net/http"
"net/url"
"net/url"
"time"
"time"
...
@@ -45,6 +47,7 @@ func main() {
...
@@ -45,6 +47,7 @@ func main() {
go
http2TunnelServer
()
go
http2TunnelServer
()
go
quicServer
()
go
quicServer
()
go
shadowUDPServer
()
go
shadowUDPServer
()
go
testServer
()
select
{}
select
{}
}
}
...
@@ -344,3 +347,13 @@ func tlsConfig() *tls.Config {
...
@@ -344,3 +347,13 @@ func tlsConfig() *tls.Config {
PreferServerCipherSuites
:
true
,
PreferServerCipherSuites
:
true
,
}
}
}
}
func
testServer
()
{
s
:=
&
http
.
Server
{
Addr
:
":18888"
,
Handler
:
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
fmt
.
Fprintln
(
w
,
"abcdefghijklmnopqrstuvwxyz"
)
}),
}
log
.
Fatal
(
s
.
ListenAndServe
())
}
gost/gost.go
View file @
97d2de15
package
gost
package
gost
import
(
import
(
"errors"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"
"time"
"github.com/go-log/log"
"github.com/go-log/log"
...
@@ -38,13 +43,66 @@ var (
...
@@ -38,13 +43,66 @@ var (
)
)
var
(
var
(
ErrSessionDead
=
errors
.
New
(
"session is dead"
)
defaultRawCert
[]
byte
defaultRawKey
[]
byte
)
)
func
init
()
{
func
init
()
{
rawCert
,
rawKey
,
err
:=
generateKeyPair
()
if
err
!=
nil
{
panic
(
err
)
}
defaultRawCert
,
defaultRawKey
=
rawCert
,
rawKey
log
.
DefaultLogger
=
&
LogLogger
{}
log
.
DefaultLogger
=
&
LogLogger
{}
}
}
func
SetLogger
(
logger
log
.
Logger
)
{
func
SetLogger
(
logger
log
.
Logger
)
{
log
.
DefaultLogger
=
logger
log
.
DefaultLogger
=
logger
}
}
func
generateKeyPair
()
(
rawCert
,
rawKey
[]
byte
,
err
error
)
{
if
defaultRawCert
!=
nil
&&
defaultRawKey
!=
nil
{
return
defaultRawCert
,
defaultRawKey
,
nil
}
// Create private key and self-signed certificate
// Adapted from https://golang.org/src/crypto/tls/generate_cert.go
priv
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
2048
)
if
err
!=
nil
{
return
}
validFor
:=
time
.
Hour
*
24
*
365
*
10
// ten years
notBefore
:=
time
.
Now
()
notAfter
:=
notBefore
.
Add
(
validFor
)
serialNumberLimit
:=
new
(
big
.
Int
)
.
Lsh
(
big
.
NewInt
(
1
),
128
)
serialNumber
,
err
:=
rand
.
Int
(
rand
.
Reader
,
serialNumberLimit
)
template
:=
x509
.
Certificate
{
SerialNumber
:
serialNumber
,
Subject
:
pkix
.
Name
{
Organization
:
[]
string
{
"gost"
},
},
NotBefore
:
notBefore
,
NotAfter
:
notAfter
,
KeyUsage
:
x509
.
KeyUsageKeyEncipherment
|
x509
.
KeyUsageDigitalSignature
,
ExtKeyUsage
:
[]
x509
.
ExtKeyUsage
{
x509
.
ExtKeyUsageServerAuth
},
BasicConstraintsValid
:
true
,
}
derBytes
,
err
:=
x509
.
CreateCertificate
(
rand
.
Reader
,
&
template
,
&
template
,
&
priv
.
PublicKey
,
priv
)
if
err
!=
nil
{
return
}
rawCert
=
pem
.
EncodeToMemory
(
&
pem
.
Block
{
Type
:
"CERTIFICATE"
,
Bytes
:
derBytes
})
rawKey
=
pem
.
EncodeToMemory
(
&
pem
.
Block
{
Type
:
"RSA PRIVATE KEY"
,
Bytes
:
x509
.
MarshalPKCS1PrivateKey
(
priv
)})
return
}
// SetDefaultCertificate replaces the default certificate by your own
func
SetDefaultCertificate
(
rawCert
,
rawKey
[]
byte
)
{
defaultRawCert
=
rawCert
defaultRawKey
=
rawKey
}
gost/handler.go
View file @
97d2de15
...
@@ -17,6 +17,8 @@ type HandlerOptions struct {
...
@@ -17,6 +17,8 @@ type HandlerOptions struct {
Chain
*
Chain
Chain
*
Chain
Users
[]
*
url
.
Userinfo
Users
[]
*
url
.
Userinfo
TLSConfig
*
tls
.
Config
TLSConfig
*
tls
.
Config
Whitelist
*
Permissions
Blacklist
*
Permissions
}
}
// HandlerOption allows a common way to set handler options.
// HandlerOption allows a common way to set handler options.
...
@@ -49,3 +51,17 @@ func TLSConfigHandlerOption(config *tls.Config) HandlerOption {
...
@@ -49,3 +51,17 @@ func TLSConfigHandlerOption(config *tls.Config) HandlerOption {
opts
.
TLSConfig
=
config
opts
.
TLSConfig
=
config
}
}
}
}
// WhitelistHandlerOption sets the Whitelist option of HandlerOptions.
func
WhitelistHandlerOption
(
whitelist
*
Permissions
)
HandlerOption
{
return
func
(
opts
*
HandlerOptions
)
{
opts
.
Whitelist
=
whitelist
}
}
// BlacklistHandlerOption sets the Blacklist option of HandlerOptions.
func
BlacklistHandlerOption
(
blacklist
*
Permissions
)
HandlerOption
{
return
func
(
opts
*
HandlerOptions
)
{
opts
.
Blacklist
=
blacklist
}
}
gost/http.go
View file @
97d2de15
...
@@ -121,6 +121,17 @@ func (h *httpHandler) Handle(conn net.Conn) {
...
@@ -121,6 +121,17 @@ func (h *httpHandler) Handle(conn net.Conn) {
req
.
Header
.
Del
(
"Proxy-Authorization"
)
req
.
Header
.
Del
(
"Proxy-Authorization"
)
req
.
Header
.
Del
(
"Proxy-Connection"
)
req
.
Header
.
Del
(
"Proxy-Connection"
)
if
!
Can
(
"tcp"
,
req
.
Host
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
log
.
Logf
(
"[http] Unauthorized to tcp connect to %s"
,
req
.
Host
)
b
:=
[]
byte
(
"HTTP/1.1 403 Forbidden
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
conn
.
Write
(
b
)
if
Debug
{
log
.
Logf
(
"[http] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
string
(
b
))
}
return
}
// forward http request
// forward http request
lastNode
:=
h
.
options
.
Chain
.
LastNode
()
lastNode
:=
h
.
options
.
Chain
.
LastNode
()
if
req
.
Method
!=
http
.
MethodConnect
&&
lastNode
.
Protocol
==
"http"
{
if
req
.
Method
!=
http
.
MethodConnect
&&
lastNode
.
Protocol
==
"http"
{
...
@@ -128,11 +139,6 @@ func (h *httpHandler) Handle(conn net.Conn) {
...
@@ -128,11 +139,6 @@ func (h *httpHandler) Handle(conn net.Conn) {
return
return
}
}
// if !s.Base.Node.Can("tcp", req.Host) {
// glog.Errorf("Unauthorized to tcp connect to %s", req.Host)
// return
// }
host
:=
req
.
Host
host
:=
req
.
Host
if
!
strings
.
Contains
(
req
.
Host
,
":"
)
{
if
!
strings
.
Contains
(
req
.
Host
,
":"
)
{
host
+=
":80"
host
+=
":80"
...
...
gost/http2.go
View file @
97d2de15
...
@@ -287,10 +287,11 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
...
@@ -287,10 +287,11 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
w
.
Header
()
.
Set
(
"Proxy-Agent"
,
"gost/"
+
Version
)
w
.
Header
()
.
Set
(
"Proxy-Agent"
,
"gost/"
+
Version
)
//! if !s.Base.Node.Can("tcp", target) {
if
!
Can
(
"tcp"
,
target
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("Unauthorized to tcp connect to %s", target)
log
.
Logf
(
"[http2] Unauthorized to tcp connect to %s"
,
target
)
//! return
w
.
WriteHeader
(
http
.
StatusForbidden
)
//! }
return
}
u
,
p
,
_
:=
basicProxyAuth
(
r
.
Header
.
Get
(
"Proxy-Authorization"
))
u
,
p
,
_
:=
basicProxyAuth
(
r
.
Header
.
Get
(
"Proxy-Authorization"
))
if
!
authenticate
(
u
,
p
,
h
.
options
.
Users
...
)
{
if
!
authenticate
(
u
,
p
,
h
.
options
.
Users
...
)
{
...
...
gost/log.go
View file @
97d2de15
...
@@ -21,7 +21,7 @@ func (l *LogLogger) Logf(format string, v ...interface{}) {
...
@@ -21,7 +21,7 @@ func (l *LogLogger) Logf(format string, v ...interface{}) {
log
.
Output
(
3
,
fmt
.
Sprintf
(
format
,
v
...
))
log
.
Output
(
3
,
fmt
.
Sprintf
(
format
,
v
...
))
}
}
// NopLogger is a
null
logger that discards the log outputs
// NopLogger is a
dummy
logger that discards the log outputs
type
NopLogger
struct
{
type
NopLogger
struct
{
}
}
...
...
gost/node.go
View file @
97d2de15
package
gost
package
gost
import
(
import
(
"bufio"
"net"
"net/url"
"net/url"
"os"
"strconv"
"strings"
"github.com/go-log/log"
)
)
// Node is a proxy node, mainly used to construct a proxy chain.
// Node is a proxy node, mainly used to construct a proxy chain.
type
Node
struct
{
type
Node
struct
{
Addr
string
Addr
string
Protocol
string
Protocol
string
Transport
string
Transport
string
User
*
url
.
Userinfo
Remote
string
// remote address, used by tcp/udp port forwarding
Client
*
Client
User
*
url
.
Userinfo
Server
*
Server
users
[]
*
url
.
Userinfo
// authentication or cipher for proxy
Whitelist
*
Permissions
Blacklist
*
Permissions
values
url
.
Values
serverName
string
Client
*
Client
Server
*
Server
}
func
ParseNode
(
s
string
)
(
node
Node
,
err
error
)
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
s
=
"auto://"
+
s
}
u
,
err
:=
url
.
Parse
(
s
)
if
err
!=
nil
{
return
}
query
:=
u
.
Query
()
node
=
Node
{
Addr
:
u
.
Host
,
values
:
query
,
serverName
:
u
.
Host
,
}
if
query
.
Get
(
"whitelist"
)
!=
""
{
if
node
.
Whitelist
,
err
=
ParsePermissions
(
query
.
Get
(
"whitelist"
));
err
!=
nil
{
return
}
}
else
{
// By default allow for everyting
node
.
Whitelist
,
_
=
ParsePermissions
(
"*:*:*"
)
}
if
query
.
Get
(
"blacklist"
)
!=
""
{
if
node
.
Blacklist
,
err
=
ParsePermissions
(
query
.
Get
(
"blacklist"
));
err
!=
nil
{
return
}
}
else
{
// By default block nothing
node
.
Blacklist
,
_
=
ParsePermissions
(
""
)
}
if
u
.
User
!=
nil
{
node
.
User
=
u
.
User
node
.
users
=
append
(
node
.
users
,
u
.
User
)
}
users
,
er
:=
parseUsers
(
node
.
values
.
Get
(
"secrets"
))
if
users
!=
nil
{
node
.
users
=
append
(
node
.
users
,
users
...
)
}
if
er
!=
nil
{
log
.
Log
(
"load secrets:"
,
er
)
}
if
strings
.
Contains
(
u
.
Host
,
":"
)
{
node
.
serverName
,
_
,
_
=
net
.
SplitHostPort
(
u
.
Host
)
if
node
.
serverName
==
""
{
node
.
serverName
=
"localhost"
// default server name
}
}
schemes
:=
strings
.
Split
(
u
.
Scheme
,
"+"
)
if
len
(
schemes
)
==
1
{
node
.
Protocol
=
schemes
[
0
]
node
.
Transport
=
schemes
[
0
]
}
if
len
(
schemes
)
==
2
{
node
.
Protocol
=
schemes
[
0
]
node
.
Transport
=
schemes
[
1
]
}
switch
node
.
Transport
{
case
"tls"
,
"ws"
,
"wss"
,
"kcp"
,
"ssh"
,
"quic"
,
"ssu"
,
"http2"
,
"h2"
,
"h2c"
,
"redirect"
:
case
"https"
:
node
.
Protocol
=
"http"
node
.
Transport
=
"tls"
case
"tcp"
,
"udp"
:
// started from v2.1, tcp and udp are for local port forwarding
node
.
Remote
=
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
)
case
"rtcp"
,
"rudp"
:
// rtcp and rudp are for remote port forwarding
node
.
Remote
=
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
)
default
:
node
.
Transport
=
""
}
switch
node
.
Protocol
{
case
"http"
,
"http2"
,
"socks4"
,
"socks4a"
,
"socks"
,
"socks5"
,
"ss"
:
case
"tcp"
,
"udp"
,
"rtcp"
,
"rudp"
:
// port forwarding
case
"direct"
,
"remote"
:
// SSH port forwarding
default
:
node
.
Protocol
=
""
}
return
}
func
parseUsers
(
authFile
string
)
(
users
[]
*
url
.
Userinfo
,
err
error
)
{
if
authFile
==
""
{
return
}
file
,
err
:=
os
.
Open
(
authFile
)
if
err
!=
nil
{
return
}
scanner
:=
bufio
.
NewScanner
(
file
)
for
scanner
.
Scan
()
{
line
:=
strings
.
TrimSpace
(
scanner
.
Text
())
if
line
==
""
||
strings
.
HasPrefix
(
line
,
"#"
)
{
continue
}
s
:=
strings
.
SplitN
(
line
,
" "
,
2
)
if
len
(
s
)
==
1
{
users
=
append
(
users
,
url
.
User
(
strings
.
TrimSpace
(
s
[
0
])))
}
else
if
len
(
s
)
==
2
{
users
=
append
(
users
,
url
.
UserPassword
(
strings
.
TrimSpace
(
s
[
0
]),
strings
.
TrimSpace
(
s
[
1
])))
}
}
err
=
scanner
.
Err
()
return
}
func
Can
(
action
string
,
addr
string
,
whitelist
,
blacklist
*
Permissions
)
bool
{
if
!
strings
.
Contains
(
addr
,
":"
)
{
addr
=
addr
+
":80"
}
host
,
strport
,
err
:=
net
.
SplitHostPort
(
addr
)
if
err
!=
nil
{
return
false
}
port
,
err
:=
strconv
.
Atoi
(
strport
)
if
err
!=
nil
{
return
false
}
log
.
Logf
(
"Can action: %s, host: %s, port %d"
,
action
,
host
,
port
)
return
whitelist
.
Can
(
action
,
host
,
port
)
&&
!
blacklist
.
Can
(
action
,
host
,
port
)
}
}
gost/permissions.go
View file @
97d2de15
...
@@ -9,14 +9,6 @@ import (
...
@@ -9,14 +9,6 @@ import (
glob
"github.com/ryanuber/go-glob"
glob
"github.com/ryanuber/go-glob"
)
)
type
PortRange
struct
{
Min
,
Max
int
}
type
PortSet
[]
PortRange
type
StringSet
[]
string
type
Permission
struct
{
type
Permission
struct
{
Actions
StringSet
Actions
StringSet
Hosts
StringSet
Hosts
StringSet
...
@@ -39,6 +31,10 @@ func maxint(x, y int) int {
...
@@ -39,6 +31,10 @@ func maxint(x, y int) int {
return
y
return
y
}
}
type
PortRange
struct
{
Min
,
Max
int
}
func
(
ir
*
PortRange
)
Contains
(
value
int
)
bool
{
func
(
ir
*
PortRange
)
Contains
(
value
int
)
bool
{
return
value
>=
ir
.
Min
&&
value
<=
ir
.
Max
return
value
>=
ir
.
Min
&&
value
<=
ir
.
Max
}
}
...
@@ -88,6 +84,8 @@ func (ps *PortSet) Contains(value int) bool {
...
@@ -88,6 +84,8 @@ func (ps *PortSet) Contains(value int) bool {
return
false
return
false
}
}
type
PortSet
[]
PortRange
func
ParsePortSet
(
s
string
)
(
*
PortSet
,
error
)
{
func
ParsePortSet
(
s
string
)
(
*
PortSet
,
error
)
{
ps
:=
&
PortSet
{}
ps
:=
&
PortSet
{}
...
@@ -120,6 +118,8 @@ func (ss *StringSet) Contains(subj string) bool {
...
@@ -120,6 +118,8 @@ func (ss *StringSet) Contains(subj string) bool {
return
false
return
false
}
}
type
StringSet
[]
string
func
ParseStringSet
(
s
string
)
(
*
StringSet
,
error
)
{
func
ParseStringSet
(
s
string
)
(
*
StringSet
,
error
)
{
ss
:=
&
StringSet
{}
ss
:=
&
StringSet
{}
if
s
==
""
{
if
s
==
""
{
...
...
gost/socks.go
View file @
97d2de15
...
@@ -395,13 +395,15 @@ func (h *socks5Handler) Handle(conn net.Conn) {
...
@@ -395,13 +395,15 @@ func (h *socks5Handler) Handle(conn net.Conn) {
func
(
h
*
socks5Handler
)
handleConnect
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
func
(
h
*
socks5Handler
)
handleConnect
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
addr
:=
req
.
Addr
.
String
()
addr
:=
req
.
Addr
.
String
()
if
!
Can
(
"tcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! if !s.Base.Node.Can("tcp", addr) {
log
.
Logf
(
"[socks5-connect] Unauthorized to tcp connect to %s"
,
addr
)
//! glog.Errorf("Unauthorized to tcp connect to %s", addr)
rep
:=
gosocks5
.
NewReply
(
gosocks5
.
NotAllowed
,
nil
)
//! rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
rep
.
Write
(
conn
)
//! rep.Write(s.conn)
if
Debug
{
//! return
log
.
Logf
(
"[socks5-connect] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
rep
)
//! }
}
return
}
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -430,13 +432,12 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
...
@@ -430,13 +432,12 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
func
(
h
*
socks5Handler
)
handleBind
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
func
(
h
*
socks5Handler
)
handleBind
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
addr
:=
req
.
Addr
.
String
()
//! if !s.Base.Node.Can("rtcp", addr) {
if
!
Can
(
"rtcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("Unauthorized to tcp bind to %s", addr)
log
.
Logf
(
"Unauthorized to tcp bind to %s"
,
addr
)
//! return
return
//! }
}
h
.
bindOn
(
conn
,
addr
)
h
.
bindOn
(
conn
,
req
.
Addr
.
String
())
return
return
}
}
...
@@ -554,14 +555,16 @@ func (h *socks5Handler) bindOn(conn net.Conn, addr string) {
...
@@ -554,14 +555,16 @@ func (h *socks5Handler) bindOn(conn net.Conn, addr string) {
}
}
func
(
h
*
socks5Handler
)
handleUDPRelay
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
func
(
h
*
socks5Handler
)
handleUDPRelay
(
conn
net
.
Conn
,
req
*
gosocks5
.
Request
)
{
//! addr := req.Addr.String()
addr
:=
req
.
Addr
.
String
()
//!
if
!
Can
(
"udp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! if !s.Base.Node.Can("udp", addr) {
log
.
Logf
(
"[socks5-udp] Unauthorized to udp connect to %s"
,
addr
)
//! glog.Errorf("Unauthorized to udp connect to %s", addr)
rep
:=
gosocks5
.
NewReply
(
gosocks5
.
NotAllowed
,
nil
)
//! rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
rep
.
Write
(
conn
)
//! rep.Write(s.conn)
if
Debug
{
//! return
log
.
Logf
(
"[socks5-udp] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
rep
)
//! }
}
return
}
relay
,
err
:=
net
.
ListenUDP
(
"udp"
,
nil
)
relay
,
err
:=
net
.
ListenUDP
(
"udp"
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -817,10 +820,10 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
...
@@ -817,10 +820,10 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
if
h
.
options
.
Chain
.
IsEmpty
()
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
addr
:=
req
.
Addr
.
String
()
addr
:=
req
.
Addr
.
String
()
//! if !s.Base.Node.Can("rudp", addr
) {
if
!
Can
(
"rudp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("
Unauthorized to udp bind to %s", addr)
log
.
Logf
(
"[socks5-udp]
Unauthorized to udp bind to %s"
,
addr
)
//!
return
return
//!
}
}
bindAddr
,
_
:=
net
.
ResolveUDPAddr
(
"udp"
,
addr
)
bindAddr
,
_
:=
net
.
ResolveUDPAddr
(
"udp"
,
addr
)
uc
,
err
:=
net
.
ListenUDP
(
"udp"
,
bindAddr
)
uc
,
err
:=
net
.
ListenUDP
(
"udp"
,
bindAddr
)
...
@@ -992,12 +995,15 @@ func (h *socks4Handler) Handle(conn net.Conn) {
...
@@ -992,12 +995,15 @@ func (h *socks4Handler) Handle(conn net.Conn) {
func
(
h
*
socks4Handler
)
handleConnect
(
conn
net
.
Conn
,
req
*
gosocks4
.
Request
)
{
func
(
h
*
socks4Handler
)
handleConnect
(
conn
net
.
Conn
,
req
*
gosocks4
.
Request
)
{
addr
:=
req
.
Addr
.
String
()
addr
:=
req
.
Addr
.
String
()
//! if !s.Base.Node.Can("tcp", addr) {
if
!
Can
(
"tcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("Unauthorized to tcp connect to %s", addr)
log
.
Logf
(
"[socks4-connect] Unauthorized to tcp connect to %s"
,
addr
)
//! rep := gosocks5.NewReply(gosocks4.Rejected, nil)
rep
:=
gosocks5
.
NewReply
(
gosocks4
.
Rejected
,
nil
)
//! rep.Write(s.conn)
rep
.
Write
(
conn
)
//! return
if
Debug
{
//! }
log
.
Logf
(
"[socks4-connect] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
rep
)
}
return
}
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
gost/ss.go
View file @
97d2de15
...
@@ -110,7 +110,6 @@ func (h *shadowHandler) Handle(conn net.Conn) {
...
@@ -110,7 +110,6 @@ func (h *shadowHandler) Handle(conn net.Conn) {
defer
conn
.
Close
()
defer
conn
.
Close
()
var
method
,
password
string
var
method
,
password
string
users
:=
h
.
options
.
Users
users
:=
h
.
options
.
Users
if
len
(
users
)
>
0
{
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
method
=
users
[
0
]
.
Username
()
...
@@ -132,6 +131,11 @@ func (h *shadowHandler) Handle(conn net.Conn) {
...
@@ -132,6 +131,11 @@ func (h *shadowHandler) Handle(conn net.Conn) {
}
}
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
if
!
Can
(
"tcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
log
.
Logf
(
"[ss] Unauthorized to tcp connect to %s"
,
addr
)
return
}
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[ss] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
...
...
gost/ssh.go
View file @
97d2de15
...
@@ -27,6 +27,10 @@ const (
...
@@ -27,6 +27,10 @@ const (
GostSSHTunnelRequest
=
"gost-tunnel"
// extended request type for ssh tunnel
GostSSHTunnelRequest
=
"gost-tunnel"
// extended request type for ssh tunnel
)
)
var
(
errSessionDead
=
errors
.
New
(
"session is dead"
)
)
type
sshDirectForwardConnector
struct
{
type
sshDirectForwardConnector
struct
{
}
}
...
@@ -188,7 +192,7 @@ func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOp
...
@@ -188,7 +192,7 @@ func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOp
}
}
if
session
.
Closed
()
{
if
session
.
Closed
()
{
delete
(
tr
.
sessions
,
opts
.
Addr
)
delete
(
tr
.
sessions
,
opts
.
Addr
)
return
nil
,
E
rrSessionDead
return
nil
,
e
rrSessionDead
}
}
return
&
sshNopConn
{
session
:
session
},
nil
return
&
sshNopConn
{
session
:
session
},
nil
...
@@ -288,7 +292,7 @@ func (tr *sshTunnelTransporter) Handshake(conn net.Conn, options ...HandshakeOpt
...
@@ -288,7 +292,7 @@ func (tr *sshTunnelTransporter) Handshake(conn net.Conn, options ...HandshakeOpt
if
session
.
Closed
()
{
if
session
.
Closed
()
{
delete
(
tr
.
sessions
,
opts
.
Addr
)
delete
(
tr
.
sessions
,
opts
.
Addr
)
return
nil
,
E
rrSessionDead
return
nil
,
e
rrSessionDead
}
}
channel
,
reqs
,
err
:=
session
.
client
.
OpenChannel
(
GostSSHTunnelRequest
,
nil
)
channel
,
reqs
,
err
:=
session
.
client
.
OpenChannel
(
GostSSHTunnelRequest
,
nil
)
...
@@ -485,10 +489,10 @@ func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr
...
@@ -485,10 +489,10 @@ func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr
log
.
Logf
(
"[ssh-tcp] %s - %s"
,
h
.
options
.
Addr
,
raddr
)
log
.
Logf
(
"[ssh-tcp] %s - %s"
,
h
.
options
.
Addr
,
raddr
)
//! if !s.Base.Node.Can("tcp", raddr
) {
if
!
Can
(
"tcp"
,
raddr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("
Unauthorized to tcp connect to %s", raddr)
log
.
Logf
(
"[ssh-tcp]
Unauthorized to tcp connect to %s"
,
raddr
)
//!
return
return
//!
}
}
conn
,
err
:=
h
.
options
.
Chain
.
Dial
(
raddr
)
conn
,
err
:=
h
.
options
.
Chain
.
Dial
(
raddr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -514,11 +518,11 @@ func (h *sshForwardHandler) tcpipForwardRequest(sshConn ssh.Conn, req *ssh.Reque
...
@@ -514,11 +518,11 @@ func (h *sshForwardHandler) tcpipForwardRequest(sshConn ssh.Conn, req *ssh.Reque
addr
:=
fmt
.
Sprintf
(
"%s:%d"
,
t
.
Host
,
t
.
Port
)
addr
:=
fmt
.
Sprintf
(
"%s:%d"
,
t
.
Host
,
t
.
Port
)
//! if !s.Base.Node.Can("rtcp", addr
) {
if
!
Can
(
"rtcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
//! glog.Errorf("
Unauthorized to tcp bind to %s", addr)
log
.
Logf
(
"[ssh-rtcp]
Unauthorized to tcp bind to %s"
,
addr
)
//!
req.Reply(false, nil)
req
.
Reply
(
false
,
nil
)
//!
return
return
//!
}
}
log
.
Log
(
"[ssh-rtcp] listening on tcp"
,
addr
)
log
.
Log
(
"[ssh-rtcp] listening on tcp"
,
addr
)
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
//tie to the client connection
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
//tie to the client connection
...
...
gost/tls.go
View file @
97d2de15
...
@@ -25,7 +25,7 @@ func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
...
@@ -25,7 +25,7 @@ func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
if
opts
.
TLSConfig
==
nil
{
if
opts
.
TLSConfig
==
nil
{
opts
.
TLSConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
opts
.
TLSConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
}
}
return
tls
.
Client
(
conn
,
opts
.
TLSConfig
),
nil
return
wrapTLSClient
(
conn
,
opts
.
TLSConfig
)
}
}
type
tlsListener
struct
{
type
tlsListener
struct
{
...
...
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