mirror of https://github.com/ginuerzh/gost
13 changed files with 1109 additions and 54 deletions
@ -0,0 +1,18 @@ |
|||||
|
-----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----- |
||||
@ -0,0 +1,27 @@ |
|||||
|
-----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----- |
||||
@ -0,0 +1,111 @@ |
|||||
|
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)) |
||||
|
} |
||||
@ -0,0 +1,277 @@ |
|||||
|
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 |
||||
|
} |
||||
Loading…
Reference in new issue