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
f88eecbe
Commit
f88eecbe
authored
Oct 12, 2015
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support forward chain
parent
d69a0930
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
130 additions
and
102 deletions
+130
-102
conn.go
conn.go
+104
-76
http.go
http.go
+3
-8
main.go
main.go
+10
-10
socks.go
socks.go
+2
-2
util.go
util.go
+11
-6
No files found.
conn.go
View file @
f88eecbe
...
@@ -211,50 +211,75 @@ func (r *reqReader) Read(p []byte) (n int, err error) {
...
@@ -211,50 +211,75 @@ func (r *reqReader) Read(p []byte) (n int, err error) {
return
return
}
}
func
connect
(
connType
,
addr
string
)
(
conn
net
.
Conn
,
err
error
)
{
func
connect
(
addr
string
)
(
conn
net
.
Conn
,
err
error
)
{
if
!
strings
.
Contains
(
addr
,
":"
)
{
if
!
strings
.
Contains
(
addr
,
":"
)
{
addr
+=
":80"
addr
+=
":80"
}
}
if
len
(
forwardArgs
)
==
0
{
if
len
(
proxyArgs
)
>
0
&&
len
(
forwardArgs
)
>
0
{
return
net
.
Dial
(
"tcp"
,
addr
)
return
connectProxyForward
(
connType
,
addr
,
proxyArgs
[
0
],
forwardArgs
[
0
])
}
}
return
forwardChain
(
addr
,
forwardArgs
[
0
],
forwardArgs
[
1
:
]
...
)
}
if
len
(
forwardArgs
)
>
0
{
func
forwardChain
(
addr
string
,
level1
Args
,
chain
...
Args
)
(
conn
net
.
Conn
,
err
error
)
{
// TODO: multi-foward
if
glog
.
V
(
LINFO
)
{
forward
:=
forwardArgs
[
0
]
glog
.
Infof
(
"forward: %s/%s %s"
,
level1
.
Protocol
,
level1
.
Transport
,
level1
.
Addr
)
return
connectForward
(
connType
,
addr
,
forward
)
}
}
if
conn
,
err
=
net
.
Dial
(
"tcp"
,
level1
.
Addr
);
err
!=
nil
{
if
len
(
proxyArgs
)
>
0
{
return
proxy
:=
proxyArgs
[
0
]
return
connectForward
(
connType
,
addr
,
proxy
)
}
}
c
,
err
:=
forward
(
conn
,
level1
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
conn
=
c
return
net
.
Dial
(
"tcp"
,
addr
)
if
len
(
chain
)
==
0
{
}
if
err
:=
establish
(
conn
,
addr
,
level1
);
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
return
}
func
connectProxyForward
(
connType
,
addr
string
,
proxy
,
forward
Args
)
(
conn
net
.
Conn
,
err
error
)
{
cur
:=
level1
return
nil
,
errors
.
New
(
"Not implemented"
)
for
_
,
arg
:=
range
chain
{
}
if
err
=
establish
(
conn
,
arg
.
Addr
,
cur
);
err
!=
nil
{
goto
exit
}
func
connectForward
(
connType
,
addr
string
,
forward
Args
)
(
conn
net
.
Conn
,
err
error
)
{
c
,
err
=
forward
(
conn
,
arg
)
if
glog
.
V
(
LINFO
)
{
if
err
!=
nil
{
glog
.
Infoln
(
forward
.
Protocol
,
"forward:"
,
forward
.
Addr
)
goto
exit
}
conn
=
c
cur
=
arg
}
}
conn
,
err
=
net
.
Dial
(
"tcp"
,
forward
.
Addr
)
exit
:
if
err
!=
nil
{
if
err
!=
nil
{
return
conn
.
Close
()
return
nil
,
err
}
if
err
:=
establish
(
conn
,
addr
,
cur
);
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
}
switch
forward
.
Transport
{
return
}
func
forward
(
conn
net
.
Conn
,
arg
Args
)
(
net
.
Conn
,
error
)
{
var
err
error
switch
arg
.
Transport
{
case
"ws"
:
// websocket connection
case
"ws"
:
// websocket connection
c
,
err
:=
wsClient
(
conn
,
forward
.
Addr
)
c
onn
,
err
=
wsClient
(
conn
,
arg
.
Addr
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
return
nil
,
err
}
}
conn
=
c
case
"tls"
:
// tls connection
case
"tls"
:
// tls connection
conn
=
tls
.
Client
(
conn
,
&
tls
.
Config
{
InsecureSkipVerify
:
true
})
conn
=
tls
.
Client
(
conn
,
&
tls
.
Config
{
InsecureSkipVerify
:
true
})
case
"tcp"
:
case
"tcp"
:
...
@@ -262,83 +287,86 @@ func connectForward(connType, addr string, forward Args) (conn net.Conn, err err
...
@@ -262,83 +287,86 @@ func connectForward(connType, addr string, forward Args) (conn net.Conn, err err
default
:
default
:
}
}
switch
forward
.
Protocol
{
switch
arg
.
Protocol
{
case
"ss"
:
// shadowsocks
case
"ss"
:
// shadowsocks
conn
.
Close
()
return
nil
,
errors
.
New
(
"Not implemented"
)
return
nil
,
errors
.
New
(
"Not implemented"
)
case
"socks"
,
"socks5"
:
case
"socks"
,
"socks5"
:
selector
:=
&
clientSelector
{
selector
:=
&
clientSelector
{
methods
:
[]
uint8
{
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
},
methods
:
[]
uint8
{
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
},
arg
:
forward
,
arg
:
arg
,
}
}
if
forward
.
EncMeth
==
"tls"
{
if
arg
.
EncMeth
==
"tls"
{
selector
.
methods
=
[]
uint8
{
MethodTLS
,
MethodTLSAuth
}
selector
.
methods
=
[]
uint8
{
MethodTLS
,
MethodTLSAuth
}
}
}
c
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
c
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
if
err
:=
c
.
Handleshake
();
err
!=
nil
{
if
err
:=
c
.
Handleshake
();
err
!=
nil
{
c
.
Close
()
return
nil
,
err
return
nil
,
err
}
}
conn
=
c
conn
=
c
case
"http"
:
fallthrough
default
:
}
host
,
port
,
_
:=
net
.
SplitHostPort
(
addr
)
return
conn
,
nil
p
,
_
:=
strconv
.
ParseUint
(
port
,
10
,
16
)
}
r
:=
gosocks5
.
NewRequest
(
gosocks5
.
CmdConnect
,
&
gosocks5
.
Addr
{
func
establish
(
conn
net
.
Conn
,
addr
string
,
arg
Args
)
error
{
switch
arg
.
Protocol
{
case
"ss"
:
// shadowsocks
return
nil
case
"socks"
,
"socks5"
:
host
,
port
,
err
:=
net
.
SplitHostPort
(
addr
)
p
,
_
:=
strconv
.
Atoi
(
port
)
// TODO: support bind and udp
req
:=
gosocks5
.
NewRequest
(
gosocks5
.
CmdConnect
,
&
gosocks5
.
Addr
{
Type
:
gosocks5
.
AddrDomain
,
Type
:
gosocks5
.
AddrDomain
,
Host
:
host
,
Host
:
host
,
Port
:
uint16
(
p
),
Port
:
uint16
(
p
),
})
})
rep
,
err
:=
requestSocks5
(
conn
,
r
)
rep
,
err
:=
requestSocks5
(
conn
,
r
eq
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
return
err
return
nil
,
err
}
}
if
rep
.
Rep
!=
gosocks5
.
Succeeded
{
if
rep
.
Rep
!=
gosocks5
.
Succeeded
{
conn
.
Close
()
return
errors
.
New
(
"Service unavailable"
)
return
nil
,
errors
.
New
(
"Service unavailable"
)
}
}
case
"http"
:
case
"http"
:
fallthrough
fallthrough
default
:
default
:
if
connType
==
ConnHttpConnect
||
connType
==
ConnSocks5
{
req
:=
&
http
.
Request
{
req
:=
&
http
.
Request
{
Method
:
"CONNECT"
,
Method
:
"CONNECT"
,
URL
:
&
url
.
URL
{
Host
:
addr
},
URL
:
&
url
.
URL
{
Host
:
addr
},
Host
:
addr
,
Host
:
addr
,
ProtoMajor
:
1
,
ProtoMajor
:
1
,
ProtoMinor
:
1
,
ProtoMinor
:
1
,
Header
:
make
(
http
.
Header
),
Header
:
make
(
http
.
Header
),
}
}
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
if
arg
.
User
!=
nil
{
if
forward
.
User
!=
nil
{
req
.
Header
.
Set
(
"Proxy-Authorization"
,
req
.
Header
.
Set
(
"Proxy-Authorization"
,
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
arg
.
User
.
String
())))
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
forward
.
User
.
String
())))
}
}
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
if
err
=
req
.
Write
(
conn
);
err
!=
nil
{
return
err
conn
.
Close
()
}
return
nil
,
err
if
glog
.
V
(
LDEBUG
)
{
}
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
string
(
dump
))
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
}
glog
.
Infoln
(
string
(
dump
))
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
return
err
return
nil
,
err
}
}
if
glog
.
V
(
LDEBUG
)
{
if
glog
.
V
(
LDEBUG
)
{
dump
,
_
:=
httputil
.
DumpResponse
(
resp
,
false
)
dump
,
_
:=
httputil
.
DumpResponse
(
resp
,
false
)
glog
.
Infoln
(
string
(
dump
))
glog
.
Infoln
(
string
(
dump
))
}
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
errors
.
New
(
resp
.
Status
)
conn
.
Close
()
//log.Println(resp.Status)
return
nil
,
errors
.
New
(
resp
.
Status
)
}
}
}
}
}
return
return
nil
}
}
http.go
View file @
f88eecbe
...
@@ -19,11 +19,6 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -19,11 +19,6 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
}
}
}
}
connType
:=
ConnHttp
if
req
.
Method
==
"CONNECT"
{
connType
=
ConnHttpConnect
}
var
username
,
password
string
var
username
,
password
string
if
arg
.
User
!=
nil
{
if
arg
.
User
!=
nil
{
username
=
arg
.
User
.
Username
()
username
=
arg
.
User
.
Username
()
...
@@ -52,7 +47,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -52,7 +47,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
return
return
}
}
c
,
err
:=
connect
(
connType
,
req
.
Host
)
c
,
err
:=
connect
(
req
.
Host
)
if
err
!=
nil
{
if
err
!=
nil
{
if
glog
.
V
(
LWARNING
)
{
if
glog
.
V
(
LWARNING
)
{
glog
.
Warningln
(
err
)
glog
.
Warningln
(
err
)
...
@@ -67,7 +62,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -67,7 +62,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
}
}
defer
c
.
Close
()
defer
c
.
Close
()
if
connType
==
ConnHttpConnect
{
if
req
.
Method
==
"CONNECT"
{
b
:=
[]
byte
(
"HTTP/1.1 200 Connection established
\r\n
"
+
b
:=
[]
byte
(
"HTTP/1.1 200 Connection established
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
if
glog
.
V
(
LDEBUG
)
{
if
glog
.
V
(
LDEBUG
)
{
...
@@ -80,7 +75,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -80,7 +75,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
return
return
}
}
}
else
{
}
else
{
if
len
(
proxyArgs
)
>
0
||
len
(
forwardArgs
)
>
0
{
if
len
(
forwardArgs
)
>
0
{
err
=
req
.
WriteProxy
(
c
)
err
=
req
.
WriteProxy
(
c
)
}
else
{
}
else
{
err
=
req
.
Write
(
c
)
err
=
req
.
Write
(
c
)
...
...
main.go
View file @
f88eecbe
...
@@ -16,30 +16,30 @@ const (
...
@@ -16,30 +16,30 @@ const (
)
)
var
(
var
(
listen
Url
,
proxyUrl
,
forwardUrl
string
listen
Addr
,
forwardAddr
strSlice
pv
bool
// print version
pv
bool
// print version
listenArgs
[]
Args
listenArgs
[]
Args
proxyArgs
[]
Args
forwardArgs
[]
Args
forwardArgs
[]
Args
)
)
func
init
()
{
func
init
()
{
flag
.
StringVar
(
&
listenUrl
,
"L"
,
":http"
,
"local address"
)
flag
.
Var
(
&
listenAddr
,
"L"
,
"listen address"
)
flag
.
StringVar
(
&
forwardUrl
,
"S"
,
""
,
"remote address"
)
flag
.
Var
(
&
forwardAddr
,
"F"
,
"forward address, can make a forward chain"
)
flag
.
StringVar
(
&
proxyUrl
,
"P"
,
""
,
"proxy address"
)
flag
.
BoolVar
(
&
pv
,
"V"
,
false
,
"print version"
)
flag
.
BoolVar
(
&
pv
,
"V"
,
false
,
"print version"
)
flag
.
Parse
()
flag
.
Parse
()
listenArgs
=
parseArgs
(
listenUrl
)
listenArgs
=
parseArgs
(
listenAddr
)
proxyArgs
=
parseArgs
(
proxyUrl
)
forwardArgs
=
parseArgs
(
forwardAddr
)
forwardArgs
=
parseArgs
(
forwardUrl
)
}
}
func
main
()
{
func
main
()
{
defer
glog
.
Flush
()
defer
glog
.
Flush
()
if
flag
.
NFlag
()
==
0
{
flag
.
PrintDefaults
()
return
}
if
pv
{
if
pv
{
printVersion
()
printVersion
()
return
return
...
...
socks.go
View file @
f88eecbe
...
@@ -138,7 +138,7 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
...
@@ -138,7 +138,7 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
return
nil
,
err
return
nil
,
err
}
}
if
glog
.
V
(
LDEBUG
)
{
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
req
)
glog
.
Infoln
(
req
.
String
()
)
}
}
var
username
,
password
string
var
username
,
password
string
...
@@ -206,7 +206,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
...
@@ -206,7 +206,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
if
glog
.
V
(
LINFO
)
{
if
glog
.
V
(
LINFO
)
{
glog
.
Infoln
(
"socks5 connect:"
,
req
.
Addr
.
String
())
glog
.
Infoln
(
"socks5 connect:"
,
req
.
Addr
.
String
())
}
}
tconn
,
err
:=
connect
(
ConnSocks5
,
req
.
Addr
.
String
())
tconn
,
err
:=
connect
(
req
.
Addr
.
String
())
if
err
!=
nil
{
if
err
!=
nil
{
if
glog
.
V
(
LWARNING
)
{
if
glog
.
V
(
LWARNING
)
{
glog
.
Warningln
(
"socks5 connect:"
,
err
)
glog
.
Warningln
(
"socks5 connect:"
,
err
)
...
...
util.go
View file @
f88eecbe
...
@@ -10,6 +10,16 @@ import (
...
@@ -10,6 +10,16 @@ import (
"strings"
"strings"
)
)
type
strSlice
[]
string
func
(
ss
*
strSlice
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s"
,
*
ss
)
}
func
(
ss
*
strSlice
)
Set
(
value
string
)
error
{
*
ss
=
append
(
*
ss
,
value
)
return
nil
}
// socks://admin:123456@localhost:8080/tls
// socks://admin:123456@localhost:8080/tls
type
Args
struct
{
type
Args
struct
{
Addr
string
// host:port
Addr
string
// host:port
...
@@ -32,12 +42,7 @@ func (args Args) String() string {
...
@@ -32,12 +42,7 @@ func (args Args) String() string {
args
.
EncMeth
,
args
.
EncPass
)
args
.
EncMeth
,
args
.
EncPass
)
}
}
func
parseArgs
(
rawurl
string
)
(
args
[]
Args
)
{
func
parseArgs
(
ss
[]
string
)
(
args
[]
Args
)
{
ss
:=
strings
.
Split
(
rawurl
,
","
)
if
rawurl
==
""
||
len
(
ss
)
==
0
{
return
nil
}
for
_
,
s
:=
range
ss
{
for
_
,
s
:=
range
ss
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
s
=
"tcp://"
+
s
s
=
"tcp://"
+
s
...
...
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