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
346c2c27
Commit
346c2c27
authored
Jul 24, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add HTTP2 proxy support
parent
1c76ca4b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
581 additions
and
73 deletions
+581
-73
gost/cli/cli.go
gost/cli/cli.go
+48
-25
gost/client.go
gost/client.go
+6
-0
gost/gost.go
gost/gost.go
+4
-0
gost/http.go
gost/http.go
+20
-16
gost/http2.go
gost/http2.go
+444
-0
gost/kcp.go
gost/kcp.go
+5
-1
gost/srv/srv.go
gost/srv/srv.go
+37
-27
gost/ssh.go
gost/ssh.go
+1
-0
gost/tls.go
gost/tls.go
+8
-4
gost/ws.go
gost/ws.go
+8
-0
No files found.
gost/cli/cli.go
View file @
346c2c27
...
...
@@ -2,9 +2,13 @@ package main
import
(
"bufio"
"crypto/tls"
"log"
"net/http"
"net/http/httputil"
"net/url"
"time"
"github.com/ginuerzh/gost/gost"
)
...
...
@@ -85,36 +89,55 @@ func main() {
},
*/
// http
+kcp
// http
2
gost
.
Node
{
Addr
:
"127.0.0.1:
8388
"
,
Addr
:
"127.0.0.1:
1443
"
,
Client
:
gost
.
NewClient
(
gost
.
HTTPConnector
(
nil
),
gost
.
KCPTransporter
(
nil
),
gost
.
HTTP2Connector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
gost
.
HTTP2Transporter
(
nil
,
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
time
.
Second
*
60
,
),
),
},
/*
// http+kcp
gost.Node{
Addr: "127.0.0.1:8388",
Client: gost.NewClient(
gost.HTTPConnector(nil),
gost.KCPTransporter(nil),
),
},
*/
)
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://localhost:10000/pkg"
,
nil
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
log
.
Fatal
(
err
)
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
defer
resp
.
Body
.
Close
()
for
i
:=
0
;
i
<
10
;
i
++
{
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://localhost:10000/pkg"
,
nil
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
log
.
Fatal
(
err
)
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
defer
resp
.
Body
.
Close
()
rb
,
_
:=
httputil
.
DumpRequest
(
req
,
true
)
log
.
Println
(
string
(
rb
))
rb
,
_
=
httputil
.
DumpResponse
(
resp
,
true
)
log
.
Println
(
string
(
rb
))
rb
,
_
:=
httputil
.
DumpRequest
(
req
,
true
)
log
.
Println
(
string
(
rb
))
rb
,
_
=
httputil
.
DumpResponse
(
resp
,
true
)
log
.
Println
(
string
(
rb
))
time
.
Sleep
(
100
*
time
.
Millisecond
)
}
}
gost/client.go
View file @
346c2c27
...
...
@@ -63,6 +63,8 @@ type Connector interface {
type
Transporter
interface
{
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
// Indicate that the Transporter supports multiplex
Multiplex
()
bool
}
type
tcpTransporter
struct
{
...
...
@@ -80,3 +82,7 @@ func (tr *tcpTransporter) Dial(addr string) (net.Conn, error) {
func
(
tr
*
tcpTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
}
func
(
tr
*
tcpTransporter
)
Multiplex
()
bool
{
return
false
}
gost/gost.go
View file @
346c2c27
...
...
@@ -28,6 +28,10 @@ var (
ReadTimeout
=
30
*
time
.
Second
// WriteTimeout is the timeout for writing.
WriteTimeout
=
60
*
time
.
Second
// PingTimeout is the timeout for pinging.
PingTimeout
=
30
*
time
.
Second
// PingRetries is the reties of ping.
PingRetries
=
3
// default udp node TTL in second for udp port forwarding.
defaultTTL
=
60
)
...
...
gost/http.go
View file @
346c2c27
...
...
@@ -110,21 +110,8 @@ func (h *httpHandler) Handle(conn net.Conn) {
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
{
u
,
p
,
_
:=
basicProxyAuth
(
req
.
Header
.
Get
(
"Proxy-Authorization"
))
if
!
authenticate
(
u
,
p
,
h
.
options
.
Users
...
)
{
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
"
+
...
...
@@ -182,7 +169,7 @@ func (h *httpHandler) Handle(conn net.Conn) {
log
.
Logf
(
"[http] %s >-< %s"
,
conn
.
RemoteAddr
(),
req
.
Host
)
}
func
(
h
*
httpHandler
)
basicProxyAuth
(
proxyAuth
string
)
(
username
,
password
string
,
ok
bool
)
{
func
basicProxyAuth
(
proxyAuth
string
)
(
username
,
password
string
,
ok
bool
)
{
if
proxyAuth
==
""
{
return
}
...
...
@@ -202,3 +189,20 @@ func (h *httpHandler) basicProxyAuth(proxyAuth string) (username, password strin
return
cs
[
:
s
],
cs
[
s
+
1
:
],
true
}
func
authenticate
(
username
,
password
string
,
users
...*
url
.
Userinfo
)
bool
{
if
len
(
users
)
==
0
{
return
true
}
for
_
,
user
:=
range
users
{
u
:=
user
.
Username
()
p
,
_
:=
user
.
Password
()
if
(
u
==
username
&&
p
==
password
)
||
(
u
==
username
&&
p
==
""
)
||
(
u
==
""
&&
p
==
password
)
{
return
true
}
}
return
false
}
gost/http2.go
0 → 100644
View file @
346c2c27
package
gost
import
(
"bufio"
"context"
"crypto/tls"
"encoding/base64"
"errors"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"sync"
"time"
"github.com/go-log/log"
"golang.org/x/net/http2"
)
type
http2Connector
struct
{
User
*
url
.
Userinfo
}
// HTTP2Connector creates a Connector for HTTP2 proxy client.
// It accepts an optional auth info for HTTP Basic Authentication.
func
HTTP2Connector
(
user
*
url
.
Userinfo
)
Connector
{
return
&
http2Connector
{
User
:
user
}
}
func
(
c
*
http2Connector
)
Connect
(
conn
net
.
Conn
,
addr
string
)
(
net
.
Conn
,
error
)
{
cc
,
ok
:=
conn
.
(
*
http2DummyConn
)
if
!
ok
{
return
nil
,
errors
.
New
(
"conn must be a conn wrapper"
)
}
pr
,
pw
:=
io
.
Pipe
()
u
:=
&
url
.
URL
{
Host
:
addr
,
}
req
,
err
:=
http
.
NewRequest
(
"CONNECT"
,
u
.
String
(),
ioutil
.
NopCloser
(
pr
))
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s - %s : %s"
,
cc
.
raddr
,
addr
,
err
)
return
nil
,
err
}
if
c
.
User
!=
nil
{
req
.
Header
.
Set
(
"Proxy-Authorization"
,
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
c
.
User
.
String
())))
}
req
.
ProtoMajor
=
2
req
.
ProtoMinor
=
0
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
resp
,
err
:=
cc
.
conn
.
RoundTrip
(
req
)
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s - %s : %s"
,
cc
.
raddr
,
addr
,
err
)
return
nil
,
err
}
if
Debug
{
dump
,
_
:=
httputil
.
DumpResponse
(
resp
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
resp
.
Body
.
Close
()
return
nil
,
errors
.
New
(
resp
.
Status
)
}
hc
:=
&
http2Conn
{
r
:
resp
.
Body
,
w
:
pw
}
hc
.
remoteAddr
,
_
=
net
.
ResolveTCPAddr
(
"tcp"
,
cc
.
raddr
)
return
hc
,
nil
}
type
http2Transporter
struct
{
tlsConfig
*
tls
.
Config
tr
*
http2
.
Transport
chain
*
Chain
conns
map
[
string
]
*
http2
.
ClientConn
connMutex
sync
.
Mutex
pingInterval
time
.
Duration
}
// HTTP2Transporter creates a Transporter that is used by HTTP2 proxy client.
//
// Optional chain is a proxy chain that can be used to establish a connection with the HTTP2 server.
//
// Optional config is a TLS config for TLS handshake, if is nil, will use h2c mode.
//
// Optional ping is the ping interval, if is zero, ping will not be enabled.
func
HTTP2Transporter
(
chain
*
Chain
,
config
*
tls
.
Config
,
ping
time
.
Duration
)
Transporter
{
return
&
http2Transporter
{
tlsConfig
:
config
,
tr
:
new
(
http2
.
Transport
),
chain
:
chain
,
pingInterval
:
ping
,
conns
:
make
(
map
[
string
]
*
http2
.
ClientConn
),
}
}
func
(
tr
*
http2Transporter
)
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
tr
.
connMutex
.
Lock
()
conn
,
ok
:=
tr
.
conns
[
addr
]
if
!
ok
{
cc
,
err
:=
tr
.
chain
.
Dial
(
addr
)
if
err
!=
nil
{
tr
.
connMutex
.
Unlock
()
return
nil
,
err
}
if
tr
.
tlsConfig
!=
nil
{
tc
:=
tls
.
Client
(
cc
,
tr
.
tlsConfig
)
if
err
:=
tc
.
Handshake
();
err
!=
nil
{
tr
.
connMutex
.
Unlock
()
return
nil
,
err
}
cc
=
tc
}
conn
,
err
=
tr
.
tr
.
NewClientConn
(
cc
)
if
err
!=
nil
{
tr
.
connMutex
.
Unlock
()
return
nil
,
err
}
tr
.
conns
[
addr
]
=
conn
go
tr
.
ping
(
tr
.
pingInterval
,
addr
,
conn
)
}
tr
.
connMutex
.
Unlock
()
if
!
conn
.
CanTakeNewRequest
()
{
tr
.
connMutex
.
Lock
()
delete
(
tr
.
conns
,
addr
)
// TODO: we could re-connect to the addr automatically.
tr
.
connMutex
.
Unlock
()
return
nil
,
errors
.
New
(
"connection is dead"
)
}
return
&
http2DummyConn
{
raddr
:
addr
,
conn
:
conn
,
},
nil
}
func
(
tr
*
http2Transporter
)
ping
(
interval
time
.
Duration
,
addr
string
,
conn
*
http2
.
ClientConn
)
{
if
interval
<=
0
{
return
}
log
.
Log
(
"[http2] ping is enabled, interval:"
,
interval
)
baseCtx
:=
context
.
Background
()
t
:=
time
.
NewTicker
(
interval
)
retries
:=
PingRetries
for
{
select
{
case
<-
t
.
C
:
if
!
conn
.
CanTakeNewRequest
()
{
return
}
ctx
,
cancel
:=
context
.
WithTimeout
(
baseCtx
,
PingTimeout
)
if
err
:=
conn
.
Ping
(
ctx
);
err
!=
nil
{
log
.
Logf
(
"[http2] ping: %s"
,
err
)
if
retries
>
0
{
retries
--
log
.
Log
(
"[http2] retry ping"
)
cancel
()
continue
}
// connection is dead, remove it.
tr
.
connMutex
.
Lock
()
delete
(
tr
.
conns
,
addr
)
tr
.
connMutex
.
Unlock
()
cancel
()
return
}
cancel
()
retries
=
PingRetries
}
}
}
func
(
tr
*
http2Transporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
}
func
(
tr
*
http2Transporter
)
Multiplex
()
bool
{
return
true
}
type
http2Handler
struct
{
server
*
http2
.
Server
options
*
HandlerOptions
}
// HTTP2Handler creates a server Handler for HTTP2 proxy server.
func
HTTP2Handler
(
opts
...
HandlerOption
)
Handler
{
h
:=
&
http2Handler
{
server
:
new
(
http2
.
Server
),
options
:
&
HandlerOptions
{
Chain
:
new
(
Chain
),
},
}
for
_
,
opt
:=
range
opts
{
opt
(
h
.
options
)
}
return
h
}
func
(
h
*
http2Handler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
if
tc
,
ok
:=
conn
.
(
*
tls
.
Conn
);
ok
{
// NOTE: HTTP2 server will check the TLS version,
// so we must ensure that the TLS connection is handshake completed.
if
err
:=
tc
.
Handshake
();
err
!=
nil
{
log
.
Logf
(
"[http2] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
}
opt
:=
http2
.
ServeConnOpts
{
Handler
:
http
.
HandlerFunc
(
h
.
handleFunc
),
}
h
.
server
.
ServeConn
(
conn
,
&
opt
)
}
func
(
h
*
http2Handler
)
handleFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
target
:=
r
.
Header
.
Get
(
"Gost-Target"
)
// compitable with old version
if
target
==
""
{
target
=
r
.
Host
}
log
.
Logf
(
"[http2] %s %s - %s %s"
,
r
.
Method
,
r
.
RemoteAddr
,
target
,
r
.
Proto
)
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
r
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
w
.
Header
()
.
Set
(
"Proxy-Agent"
,
"gost/"
+
Version
)
//! if !s.Base.Node.Can("tcp", target) {
//! glog.Errorf("Unauthorized to tcp connect to %s", target)
//! return
//! }
u
,
p
,
_
:=
basicProxyAuth
(
r
.
Header
.
Get
(
"Proxy-Authorization"
))
if
!
authenticate
(
u
,
p
,
h
.
options
.
Users
...
)
{
log
.
Logf
(
"[http2] %s <- %s : proxy authentication required"
,
r
.
RemoteAddr
,
target
)
w
.
Header
()
.
Set
(
"Proxy-Authenticate"
,
"Basic realm=
\"
gost
\"
"
)
w
.
WriteHeader
(
http
.
StatusProxyAuthRequired
)
return
}
r
.
Header
.
Del
(
"Proxy-Authorization"
)
r
.
Header
.
Del
(
"Proxy-Connection"
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
target
)
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s -> %s : %s"
,
r
.
RemoteAddr
,
target
,
err
)
w
.
WriteHeader
(
http
.
StatusServiceUnavailable
)
return
}
defer
cc
.
Close
()
log
.
Logf
(
"[http2] %s <-> %s"
,
r
.
RemoteAddr
,
target
)
if
r
.
Method
==
http
.
MethodConnect
{
w
.
WriteHeader
(
http
.
StatusOK
)
if
fw
,
ok
:=
w
.
(
http
.
Flusher
);
ok
{
fw
.
Flush
()
}
// compatible with HTTP1.x
if
hj
,
ok
:=
w
.
(
http
.
Hijacker
);
ok
&&
r
.
ProtoMajor
==
1
{
// we take over the underly connection
conn
,
_
,
err
:=
hj
.
Hijack
()
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s -> %s : %s"
,
r
.
RemoteAddr
,
target
,
err
)
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
return
}
defer
conn
.
Close
()
log
.
Logf
(
"[http2] %s -> %s : downgrade to HTTP/1.1"
,
r
.
RemoteAddr
,
target
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[http2] %s >-< %s"
,
r
.
RemoteAddr
,
target
)
return
}
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
_
,
err
:=
io
.
Copy
(
cc
,
r
.
Body
)
errc
<-
err
}()
go
func
()
{
_
,
err
:=
io
.
Copy
(
flushWriter
{
w
},
cc
)
errc
<-
err
}()
select
{
case
<-
errc
:
// glog.V(LWARNING).Infoln("exit", err)
}
log
.
Logf
(
"[http2] %s >-< %s"
,
r
.
RemoteAddr
,
target
)
return
}
if
err
=
r
.
Write
(
cc
);
err
!=
nil
{
log
.
Logf
(
"[http2] %s -> %s : %s"
,
r
.
RemoteAddr
,
target
,
err
)
return
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
cc
),
r
)
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s -> %s : %s"
,
r
.
RemoteAddr
,
target
,
err
)
return
}
defer
resp
.
Body
.
Close
()
for
k
,
v
:=
range
resp
.
Header
{
for
_
,
vv
:=
range
v
{
w
.
Header
()
.
Add
(
k
,
vv
)
}
}
w
.
WriteHeader
(
resp
.
StatusCode
)
if
_
,
err
:=
io
.
Copy
(
flushWriter
{
w
},
resp
.
Body
);
err
!=
nil
{
log
.
Logf
(
"[http2] %s <- %s : %s"
,
r
.
RemoteAddr
,
target
,
err
)
}
log
.
Logf
(
"[http2] %s >-< %s"
,
r
.
RemoteAddr
,
target
)
}
// HTTP2 connection, wrapped up just like a net.Conn
type
http2Conn
struct
{
r
io
.
Reader
w
io
.
Writer
remoteAddr
net
.
Addr
localAddr
net
.
Addr
}
func
(
c
*
http2Conn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
c
.
r
.
Read
(
b
)
}
func
(
c
*
http2Conn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
c
.
w
.
Write
(
b
)
}
func
(
c
*
http2Conn
)
Close
()
(
err
error
)
{
if
rc
,
ok
:=
c
.
r
.
(
io
.
Closer
);
ok
{
err
=
rc
.
Close
()
}
if
w
,
ok
:=
c
.
w
.
(
io
.
Closer
);
ok
{
err
=
w
.
Close
()
}
return
}
func
(
c
*
http2Conn
)
LocalAddr
()
net
.
Addr
{
return
c
.
localAddr
}
func
(
c
*
http2Conn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
remoteAddr
}
func
(
c
*
http2Conn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2Conn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2Conn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
// Dummy HTTP2 connection.
type
http2DummyConn
struct
{
raddr
string
conn
*
http2
.
ClientConn
}
func
(
c
*
http2DummyConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"read"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"read not supported"
)}
}
func
(
c
*
http2DummyConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"write"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"write not supported"
)}
}
func
(
c
*
http2DummyConn
)
Close
()
error
{
return
nil
}
func
(
c
*
http2DummyConn
)
LocalAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
http2DummyConn
)
RemoteAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
http2DummyConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2DummyConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2DummyConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
type
flushWriter
struct
{
w
io
.
Writer
}
func
(
fw
flushWriter
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
if
s
,
ok
:=
r
.
(
string
);
ok
{
err
=
errors
.
New
(
s
)
return
}
err
=
r
.
(
error
)
}
}()
n
,
err
=
fw
.
w
.
Write
(
p
)
if
err
!=
nil
{
// log.Log("flush writer:", err)
return
}
if
f
,
ok
:=
fw
.
w
.
(
http
.
Flusher
);
ok
{
f
.
Flush
()
}
return
}
gost/kcp.go
View file @
346c2c27
...
...
@@ -196,7 +196,7 @@ func (tr *kcpTransporter) Dial(addr string) (conn net.Conn, err error) {
if
err
!=
nil
{
tr
.
sessionMutex
.
Lock
()
session
.
Close
()
delete
(
tr
.
sessions
,
addr
)
delete
(
tr
.
sessions
,
addr
)
// TODO: we could obtain a new session automatically.
tr
.
sessionMutex
.
Unlock
()
}
return
...
...
@@ -245,6 +245,10 @@ func (tr *kcpTransporter) Handshake(conn net.Conn) (net.Conn, error) {
return
conn
,
nil
}
func
(
tr
*
kcpTransporter
)
Multiplex
()
bool
{
return
true
}
type
kcpListener
struct
{
config
*
KCPConfig
ln
*
kcp
.
Listener
...
...
gost/srv/srv.go
View file @
346c2c27
...
...
@@ -15,17 +15,18 @@ func init() {
}
func
main
()
{
go
httpServer
()
go
socks5Server
()
go
tlsServer
()
go
shadowServer
()
go
wsServer
()
go
wssServer
()
go
kcpServer
()
go
tcpForwardServer
()
go
rtcpForwardServer
()
//
go httpServer()
//
go socks5Server()
//
go tlsServer()
//
go shadowServer()
//
go wsServer()
//
go wssServer()
//
go kcpServer()
//
go tcpForwardServer()
//
go rtcpForwardServer()
// go rudpForwardServer()
go
tcpRedirectServer
()
// go tcpRedirectServer()
go
http2Server
()
select
{}
}
...
...
@@ -43,15 +44,10 @@ func httpServer() {
}
func
socks5Server
()
{
cert
,
err
:=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
SOCKS5Handler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
gost
.
TLSConfigHandlerOption
(
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}
),
gost
.
TLSConfigHandlerOption
(
tlsConfig
()
),
))
ln
,
err
:=
gost
.
TCPListener
(
":1080"
)
if
err
!=
nil
{
...
...
@@ -77,11 +73,7 @@ func tlsServer() {
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
}})
ln
,
err
:=
gost
.
TLSListener
(
":1443"
,
tlsConfig
())
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
...
...
@@ -105,12 +97,7 @@ func wssServer() {
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
}}})
ln
,
err
:=
gost
.
WSSListener
(
":8443"
,
&
gost
.
WSOptions
{
TLSConfig
:
tlsConfig
()})
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
...
...
@@ -194,3 +181,26 @@ func tcpRedirectServer() {
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
http2Server
()
{
// http2.VerboseLogs = true
s
:=
&
gost
.
Server
{}
s
.
Handle
(
gost
.
HTTP2Handler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
))
ln
,
err
:=
gost
.
TLSListener
(
":1443"
,
tlsConfig
())
// ln, err := gost.TCPListener(":1443")
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
log
.
Fatal
(
s
.
Serve
(
ln
))
}
func
tlsConfig
()
*
tls
.
Config
{
cert
,
err
:=
tls
.
LoadX509KeyPair
(
"cert.pem"
,
"key.pem"
)
if
err
!=
nil
{
panic
(
err
)
}
return
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}
}
gost/ssh.go
0 → 100644
View file @
346c2c27
package
gost
gost/tls.go
View file @
346c2c27
...
...
@@ -6,13 +6,13 @@ import (
)
type
tlsTransporter
struct
{
TLSClient
Config
*
tls
.
Config
tls
Config
*
tls
.
Config
}
// TLSTransporter creates a Transporter that is used by TLS proxy client.
// It accepts a TLS config for TLS handshake.
func
TLSTransporter
(
cfg
*
tls
.
Config
)
Transporter
{
return
&
tlsTransporter
{
TLSClient
Config
:
cfg
}
return
&
tlsTransporter
{
tls
Config
:
cfg
}
}
func
(
tr
*
tlsTransporter
)
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
...
...
@@ -20,7 +20,11 @@ func (tr *tlsTransporter) Dial(addr string) (net.Conn, error) {
}
func
(
tr
*
tlsTransporter
)
Handshake
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
return
tls
.
Client
(
conn
,
tr
.
TLSClientConfig
),
nil
return
tls
.
Client
(
conn
,
tr
.
tlsConfig
),
nil
}
func
(
tr
*
tlsTransporter
)
Multiplex
()
bool
{
return
false
}
type
tlsListener
struct
{
...
...
@@ -33,5 +37,5 @@ func TLSListener(addr string, config *tls.Config) (Listener, error) {
if
err
!=
nil
{
return
nil
,
err
}
return
&
tlsListener
{
Listener
:
ln
},
nil
return
&
tlsListener
{
ln
},
nil
}
gost/ws.go
View file @
346c2c27
...
...
@@ -120,6 +120,10 @@ func (tr *wsTransporter) Handshake(conn net.Conn) (net.Conn, error) {
return
websocketClientConn
(
url
.
String
(),
conn
,
tr
.
options
)
}
func
(
tr
*
wsTransporter
)
Multiplex
()
bool
{
return
false
}
type
wssTransporter
struct
{
addr
string
options
*
WSOptions
...
...
@@ -142,6 +146,10 @@ func (tr *wssTransporter) Handshake(conn net.Conn) (net.Conn, error) {
return
websocketClientConn
(
url
.
String
(),
conn
,
tr
.
options
)
}
func
(
tr
*
wssTransporter
)
Multiplex
()
bool
{
return
false
}
type
wsListener
struct
{
addr
net
.
Addr
upgrader
*
websocket
.
Upgrader
...
...
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