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
e19ff132
Commit
e19ff132
authored
Oct 10, 2015
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix http proxy
parent
037a79a0
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
266 additions
and
53 deletions
+266
-53
cert.pem
cert.pem
+0
-0
conn.go
conn.go
+178
-1
http.go
http.go
+50
-2
main.go
main.go
+11
-9
socks.go
socks.go
+4
-3
util.go
util.go
+23
-38
No files found.
cert
2
.pem
→
cert.pem
View file @
e19ff132
File moved
conn.go
View file @
e19ff132
...
@@ -2,18 +2,47 @@ package main
...
@@ -2,18 +2,47 @@ package main
import
(
import
(
"bufio"
"bufio"
"bytes"
"crypto/tls"
"crypto/tls"
"encoding/base64"
"errors"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gosocks5"
"github.com/golang/glog"
"github.com/golang/glog"
"io"
"io"
"net"
"net"
"net/http"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"strings"
)
const
(
ConnHttp
=
"http"
ConnHttpConnect
=
"http-connect"
ConnSocks5
=
"socks5"
)
)
func
listenAndServe
(
arg
Args
)
error
{
func
listenAndServe
(
arg
Args
)
error
{
var
ln
net
.
Listener
var
ln
net
.
Listener
var
err
error
var
err
error
if
glog
.
V
(
3
)
{
b
:=
bytes
.
Buffer
{}
b
.
WriteString
(
"listen on %s, use %s tunnel and %s protocol for data transport. "
)
if
arg
.
EncMeth
==
"tls"
{
b
.
WriteString
(
"for socks5, tls encrypt method is supported."
)
}
else
{
b
.
WriteString
(
"for socks5, tls encrypt method is NOT supported."
)
}
protocol
:=
arg
.
Protocol
if
protocol
==
""
{
protocol
=
"http/socks5"
}
glog
.
Infof
(
b
.
String
(),
arg
.
Addr
,
arg
.
Transport
,
protocol
)
}
switch
arg
.
Transport
{
switch
arg
.
Transport
{
case
"ws"
:
// websocket connection
case
"ws"
:
// websocket connection
err
=
NewWs
(
arg
)
.
ListenAndServe
()
err
=
NewWs
(
arg
)
.
ListenAndServe
()
...
@@ -26,6 +55,8 @@ func listenAndServe(arg Args) error {
...
@@ -26,6 +55,8 @@ func listenAndServe(arg Args) error {
case
"tls"
:
// tls connection
case
"tls"
:
// tls connection
ln
,
err
=
tls
.
Listen
(
"tcp"
,
arg
.
Addr
,
ln
,
err
=
tls
.
Listen
(
"tcp"
,
arg
.
Addr
,
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
arg
.
Cert
}})
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
arg
.
Cert
}})
case
"tcp"
:
fallthrough
default
:
default
:
ln
,
err
=
net
.
Listen
(
"tcp"
,
arg
.
Addr
)
ln
,
err
=
net
.
Listen
(
"tcp"
,
arg
.
Addr
)
}
}
...
@@ -36,6 +67,7 @@ func listenAndServe(arg Args) error {
...
@@ -36,6 +67,7 @@ func listenAndServe(arg Args) error {
}
}
return
err
return
err
}
}
defer
ln
.
Close
()
defer
ln
.
Close
()
for
{
for
{
...
@@ -61,11 +93,14 @@ func handleConn(conn net.Conn, arg Args) {
...
@@ -61,11 +93,14 @@ func handleConn(conn net.Conn, arg Args) {
selector
:=
&
serverSelector
{
selector
:=
&
serverSelector
{
methods
:
[]
uint8
{
methods
:
[]
uint8
{
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
,
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
,
MethodTLS
,
MethodTLSAuth
,
},
},
arg
:
arg
,
arg
:
arg
,
}
}
if
arg
.
EncMeth
==
"tls"
{
selector
.
methods
=
append
(
selector
.
methods
,
MethodTLS
,
MethodTLSAuth
)
}
switch
arg
.
Protocol
{
switch
arg
.
Protocol
{
case
"ss"
:
// shadowsocks
case
"ss"
:
// shadowsocks
return
return
...
@@ -174,3 +209,145 @@ func (r *reqReader) Read(p []byte) (n int, err error) {
...
@@ -174,3 +209,145 @@ func (r *reqReader) Read(p []byte) (n int, err error) {
return
return
}
}
func
connect
(
connType
,
addr
string
)
(
conn
net
.
Conn
,
err
error
)
{
if
!
strings
.
Contains
(
addr
,
":"
)
{
addr
+=
":80"
}
if
len
(
forwardArgs
)
>
0
{
// TODO: multi-foward
forward
:=
forwardArgs
[
0
]
return
connectForward
(
addr
,
forward
)
}
if
len
(
proxyArgs
)
>
0
{
proxy
:=
proxyArgs
[
0
]
return
connectProxy
(
connType
,
addr
,
proxy
)
}
return
net
.
Dial
(
"tcp"
,
addr
)
}
func
connectProxy
(
connType
,
addr
string
,
proxy
Args
)
(
conn
net
.
Conn
,
err
error
)
{
if
glog
.
V
(
LINFO
)
{
glog
.
Infoln
(
"connect proxy:"
,
proxy
.
Addr
)
}
conn
,
err
=
net
.
Dial
(
"tcp"
,
proxy
.
Addr
)
if
err
!=
nil
{
return
}
switch
proxy
.
Transport
{
case
"ws"
:
// websocket connection
c
,
err
:=
wsClient
(
conn
,
proxy
.
Addr
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
conn
=
c
case
"tls"
:
// tls connection
conn
=
tls
.
Client
(
conn
,
&
tls
.
Config
{
InsecureSkipVerify
:
true
})
case
"tcp"
:
fallthrough
default
:
}
switch
proxy
.
Protocol
{
case
"ss"
:
// shadowsocks
conn
.
Close
()
return
nil
,
errors
.
New
(
"Not implemented"
)
case
"socks"
,
"socks5"
:
selector
:=
&
clientSelector
{
methods
:
[]
uint8
{
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
},
arg
:
proxy
,
}
if
proxy
.
EncMeth
==
"tls"
{
selector
.
methods
=
[]
uint8
{
MethodTLS
,
MethodTLSAuth
}
}
c
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
if
err
:=
c
.
Handleshake
();
err
!=
nil
{
c
.
Close
()
return
nil
,
err
}
conn
=
c
if
connType
==
ConnHttp
||
connType
==
ConnHttpConnect
{
host
,
port
,
_
:=
net
.
SplitHostPort
(
addr
)
p
,
_
:=
strconv
.
ParseUint
(
port
,
10
,
16
)
r
:=
gosocks5
.
NewRequest
(
gosocks5
.
CmdConnect
,
&
gosocks5
.
Addr
{
Type
:
gosocks5
.
AddrDomain
,
Host
:
host
,
Port
:
uint16
(
p
),
})
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
r
.
String
())
}
if
err
:=
r
.
Write
(
conn
);
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
rep
,
err
:=
gosocks5
.
ReadReply
(
conn
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
rep
.
String
())
}
if
rep
.
Rep
!=
gosocks5
.
Succeeded
{
conn
.
Close
()
return
nil
,
errors
.
New
(
"Service unavailable"
)
}
}
case
"http"
:
fallthrough
default
:
if
connType
==
ConnHttpConnect
{
req
:=
&
http
.
Request
{
Method
:
"CONNECT"
,
URL
:
&
url
.
URL
{
Host
:
addr
},
Host
:
addr
,
ProtoMajor
:
1
,
ProtoMinor
:
1
,
Header
:
make
(
http
.
Header
),
}
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
if
proxy
.
User
!=
nil
{
req
.
Header
.
Set
(
"Proxy-Authorization"
,
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
proxy
.
User
.
String
())))
}
if
err
=
req
.
Write
(
conn
);
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
if
glog
.
V
(
LDEBUG
)
{
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
glog
.
Infoln
(
string
(
dump
))
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
if
glog
.
V
(
LDEBUG
)
{
dump
,
_
:=
httputil
.
DumpResponse
(
resp
,
false
)
glog
.
Infoln
(
string
(
dump
))
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
conn
.
Close
()
//log.Println(resp.Status)
return
nil
,
errors
.
New
(
resp
.
Status
)
}
}
}
return
}
func
connectForward
(
addr
string
,
forward
Args
)
(
net
.
Conn
,
error
)
{
return
nil
,
errors
.
New
(
"Not implemented"
)
}
http.go
View file @
e19ff132
...
@@ -19,13 +19,18 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -19,13 +19,18 @@ 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
()
password
,
_
=
arg
.
User
.
Password
()
password
,
_
=
arg
.
User
.
Password
()
}
}
u
,
p
,
_
:=
proxyB
asicAuth
(
req
.
Header
.
Get
(
"Proxy-Authorization"
))
u
,
p
,
_
:=
b
asicAuth
(
req
.
Header
.
Get
(
"Proxy-Authorization"
))
req
.
Header
.
Del
(
"Proxy-Authorization"
)
req
.
Header
.
Del
(
"Proxy-Authorization"
)
if
(
username
!=
""
&&
u
!=
username
)
||
(
password
!=
""
&&
p
!=
password
)
{
if
(
username
!=
""
&&
u
!=
username
)
||
(
password
!=
""
&&
p
!=
password
)
{
...
@@ -46,9 +51,52 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
...
@@ -46,9 +51,52 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
}
}
return
return
}
}
c
,
err
:=
connect
(
connType
,
req
.
Host
)
if
err
!=
nil
{
if
glog
.
V
(
LWARNING
)
{
glog
.
Warningln
(
err
)
}
b
:=
[]
byte
(
"HTTP/1.1 503 Service unavailable
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
string
(
b
))
}
conn
.
Write
(
b
)
return
}
defer
c
.
Close
()
if
connType
==
ConnHttpConnect
{
b
:=
[]
byte
(
"HTTP/1.1 200 Connection established
\r\n
"
+
"Proxy-Agent: gost/"
+
Version
+
"
\r\n\r\n
"
)
if
glog
.
V
(
LDEBUG
)
{
glog
.
Infoln
(
string
(
b
))
}
if
_
,
err
:=
conn
.
Write
(
b
);
err
!=
nil
{
if
glog
.
V
(
LWARNING
)
{
glog
.
Warningln
(
err
)
}
return
}
}
else
{
if
len
(
proxyArgs
)
>
0
{
err
=
req
.
WriteProxy
(
c
)
}
else
{
err
=
req
.
Write
(
c
)
}
if
err
!=
nil
{
if
glog
.
V
(
LWARNING
)
{
glog
.
Warningln
(
err
)
}
return
}
}
Transport
(
conn
,
c
)
}
}
func
proxyB
asicAuth
(
authInfo
string
)
(
username
,
password
string
,
ok
bool
)
{
func
b
asicAuth
(
authInfo
string
)
(
username
,
password
string
,
ok
bool
)
{
if
authInfo
==
""
{
if
authInfo
==
""
{
return
return
}
}
...
...
main.go
View file @
e19ff132
...
@@ -17,6 +17,7 @@ const (
...
@@ -17,6 +17,7 @@ const (
var
(
var
(
listenUrl
,
proxyUrl
,
forwardUrl
string
listenUrl
,
proxyUrl
,
forwardUrl
string
pv
bool
// print version
listenArgs
[]
Args
listenArgs
[]
Args
proxyArgs
[]
Args
proxyArgs
[]
Args
...
@@ -27,6 +28,7 @@ func init() {
...
@@ -27,6 +28,7 @@ func init() {
flag
.
StringVar
(
&
listenUrl
,
"L"
,
":http"
,
"local address"
)
flag
.
StringVar
(
&
listenUrl
,
"L"
,
":http"
,
"local address"
)
flag
.
StringVar
(
&
forwardUrl
,
"S"
,
""
,
"remote address"
)
flag
.
StringVar
(
&
forwardUrl
,
"S"
,
""
,
"remote address"
)
flag
.
StringVar
(
&
proxyUrl
,
"P"
,
""
,
"proxy address"
)
flag
.
StringVar
(
&
proxyUrl
,
"P"
,
""
,
"proxy address"
)
flag
.
BoolVar
(
&
pv
,
"V"
,
false
,
"print version"
)
flag
.
Parse
()
flag
.
Parse
()
...
@@ -38,22 +40,22 @@ func init() {
...
@@ -38,22 +40,22 @@ func init() {
func
main
()
{
func
main
()
{
defer
glog
.
Flush
()
defer
glog
.
Flush
()
if
pv
{
printVersion
()
return
}
if
len
(
listenArgs
)
==
0
{
if
len
(
listenArgs
)
==
0
{
glog
.
Fatalln
(
"no listen addr"
)
glog
.
Fatalln
(
"no listen addr"
)
}
}
var
wg
sync
.
WaitGroup
var
wg
sync
.
WaitGroup
for
_
,
args
:=
range
listenArgs
{
for
_
,
arg
:=
range
listenArgs
{
wg
.
Add
(
1
)
wg
.
Add
(
1
)
go
func
()
{
go
func
(
arg
Args
)
{
defer
wg
.
Done
()
defer
wg
.
Done
()
if
err
:=
listenAndServe
(
arg
);
err
!=
nil
{
listenAndServe
(
arg
)
if
glog
.
V
(
LFATAL
)
{
}(
args
)
glog
.
Errorln
(
err
)
}
}
}()
}
}
wg
.
Wait
()
wg
.
Wait
()
}
}
socks.go
View file @
e19ff132
...
@@ -14,11 +14,12 @@ const (
...
@@ -14,11 +14,12 @@ const (
)
)
type
clientSelector
struct
{
type
clientSelector
struct
{
arg
Args
methods
[]
uint8
arg
Args
}
}
func
(
selector
*
clientSelector
)
Methods
()
[]
uint8
{
func
(
selector
*
clientSelector
)
Methods
()
[]
uint8
{
return
nil
return
selector
.
methods
}
}
func
(
selector
*
clientSelector
)
Select
(
methods
...
uint8
)
(
method
uint8
)
{
func
(
selector
*
clientSelector
)
Select
(
methods
...
uint8
)
(
method
uint8
)
{
...
@@ -187,7 +188,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
...
@@ -187,7 +188,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
(
req
.
Addr
.
String
())
tconn
,
err
:=
connect
(
ConnSocks5
,
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 @
e19ff132
...
@@ -2,7 +2,6 @@ package main
...
@@ -2,7 +2,6 @@ package main
import
(
import
(
"crypto/tls"
"crypto/tls"
"errors"
"fmt"
"fmt"
"github.com/golang/glog"
"github.com/golang/glog"
"io"
"io"
...
@@ -11,10 +10,10 @@ import (
...
@@ -11,10 +10,10 @@ import (
"strings"
"strings"
)
)
// socks://admin:123456@localhost:8080
// socks://admin:123456@localhost:8080
/tls
type
Args
struct
{
type
Args
struct
{
Addr
string
// host:port
Addr
string
// host:port
Protocol
string
// protocol: h
s/http/socks/socks5/ss, default is hs(http+socks5)
Protocol
string
// protocol: h
ttp&socks5/http/socks/socks5/ss, default is http&socks5
Transport
string
// transport: tcp/ws/tls, default is tcp(raw tcp)
Transport
string
// transport: tcp/ws/tls, default is tcp(raw tcp)
User
*
url
.
Userinfo
User
*
url
.
Userinfo
EncMeth
string
// data encryption method
EncMeth
string
// data encryption method
...
@@ -41,7 +40,7 @@ func parseArgs(rawurl string) (args []Args) {
...
@@ -41,7 +40,7 @@ func parseArgs(rawurl string) (args []Args) {
for
_
,
s
:=
range
ss
{
for
_
,
s
:=
range
ss
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
if
!
strings
.
Contains
(
s
,
"://"
)
{
s
=
"
hs
://"
+
s
s
=
"
tcp
://"
+
s
}
}
u
,
err
:=
url
.
Parse
(
s
)
u
,
err
:=
url
.
Parse
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -58,23 +57,23 @@ func parseArgs(rawurl string) (args []Args) {
...
@@ -58,23 +57,23 @@ func parseArgs(rawurl string) (args []Args) {
schemes
:=
strings
.
Split
(
u
.
Scheme
,
"+"
)
schemes
:=
strings
.
Split
(
u
.
Scheme
,
"+"
)
if
len
(
schemes
)
==
1
{
if
len
(
schemes
)
==
1
{
switch
schemes
[
0
]
{
arg
.
Protocol
=
schemes
[
0
]
case
"http"
,
"socks"
,
"socks5"
,
"ss"
:
arg
.
Transport
=
schemes
[
0
]
arg
.
Protocol
=
schemes
[
0
]
case
"ws"
,
"tls"
,
"tcp"
:
arg
.
Transport
=
schemes
[
0
]
}
}
}
if
len
(
schemes
)
==
2
{
if
len
(
schemes
)
==
2
{
arg
.
Protocol
=
schemes
[
0
]
arg
.
Protocol
=
schemes
[
0
]
arg
.
Transport
=
schemes
[
1
]
arg
.
Transport
=
schemes
[
1
]
}
}
arg
.
Cert
,
err
=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
switch
arg
.
Protocol
{
if
err
!=
nil
{
case
"http"
,
"socks"
,
"socks5"
,
"ss"
:
if
glog
.
V
(
LFATAL
)
{
default
:
glog
.
Errorln
(
err
,
", tls will not be supported"
)
arg
.
Protocol
=
""
}
}
switch
arg
.
Transport
{
case
"ws"
,
"tls"
,
"tcp"
:
default
:
arg
.
Transport
=
"tcp"
}
}
mp
:=
strings
.
Split
(
strings
.
Trim
(
u
.
Path
,
"/"
),
":"
)
mp
:=
strings
.
Split
(
strings
.
Trim
(
u
.
Path
,
"/"
),
":"
)
...
@@ -85,8 +84,15 @@ func parseArgs(rawurl string) (args []Args) {
...
@@ -85,8 +84,15 @@ func parseArgs(rawurl string) (args []Args) {
arg
.
EncMeth
=
mp
[
0
]
arg
.
EncMeth
=
mp
[
0
]
arg
.
EncPass
=
mp
[
1
]
arg
.
EncPass
=
mp
[
1
]
}
}
if
glog
.
V
(
LINFO
)
{
glog
.
Infoln
(
arg
)
if
arg
.
Transport
==
"tls"
||
arg
.
EncMeth
==
"tls"
{
arg
.
Cert
,
err
=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
if
err
!=
nil
{
if
glog
.
V
(
LFATAL
)
{
glog
.
Errorln
(
err
)
}
continue
}
}
}
args
=
append
(
args
,
arg
)
args
=
append
(
args
,
arg
)
}
}
...
@@ -94,27 +100,6 @@ func parseArgs(rawurl string) (args []Args) {
...
@@ -94,27 +100,6 @@ func parseArgs(rawurl string) (args []Args) {
return
return
}
}
func
connect
(
addr
string
)
(
net
.
Conn
,
error
)
{
if
!
strings
.
Contains
(
addr
,
":"
)
{
addr
+=
":80"
}
/*
if proxyURL == nil {
return dial(addr)
}
switch proxyURL.Scheme {
case "socks": // socks5 proxy
return connectSocks5Proxy(addr)
case "http": // http proxy
fallthrough
default:
return connectHTTPProxy(addr)
}
*/
return
nil
,
errors
.
New
(
"not implemented"
)
}
// based on io.Copy
// based on io.Copy
func
Copy
(
dst
io
.
Writer
,
src
io
.
Reader
)
(
written
int64
,
err
error
)
{
func
Copy
(
dst
io
.
Writer
,
src
io
.
Reader
)
(
written
int64
,
err
error
)
{
buf
:=
make
([]
byte
,
32
*
1024
)
buf
:=
make
([]
byte
,
32
*
1024
)
...
...
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