mirror of https://github.com/ginuerzh/gost
5 changed files with 413 additions and 278 deletions
@ -3,13 +3,14 @@ package main |
|||||
|
|
||||
import ( |
import ( |
||||
"flag" |
"flag" |
||||
"github.com/ginuerzh/gosocks5" |
//"github.com/ginuerzh/gosocks5"
|
||||
"log" |
"log" |
||||
"time" |
"time" |
||||
) |
) |
||||
|
|
||||
var ( |
var ( |
||||
Laddr, Saddr, Proxy string |
Laddr, Saddr, Proxy string |
||||
|
Websocket bool |
||||
Shadows bool |
Shadows bool |
||||
SMethod, SPassword string |
SMethod, SPassword string |
||||
Method, Password string |
Method, Password string |
||||
@ -25,6 +26,7 @@ func init() { |
|||||
flag.StringVar(&CertFile, "cert", "", "cert file for tls") |
flag.StringVar(&CertFile, "cert", "", "cert file for tls") |
||||
flag.StringVar(&KeyFile, "key", "", "key file for tls") |
flag.StringVar(&KeyFile, "key", "", "key file for tls") |
||||
flag.BoolVar(&Shadows, "ss", false, "run as shadowsocks server") |
flag.BoolVar(&Shadows, "ss", false, "run as shadowsocks server") |
||||
|
flag.BoolVar(&Websocket, "ws", false, "use websocket for tunnel") |
||||
flag.StringVar(&SMethod, "sm", "rc4-md5", "shadowsocks cipher method") |
flag.StringVar(&SMethod, "sm", "rc4-md5", "shadowsocks cipher method") |
||||
flag.StringVar(&SPassword, "sp", "[email protected]", "shadowsocks cipher password") |
flag.StringVar(&SPassword, "sp", "[email protected]", "shadowsocks cipher password") |
||||
flag.Parse() |
flag.Parse() |
||||
@ -41,13 +43,13 @@ var ( |
|||||
func main() { |
func main() { |
||||
//log.Fatal(gost.Run())
|
//log.Fatal(gost.Run())
|
||||
if len(Saddr) == 0 { |
if len(Saddr) == 0 { |
||||
srv := &gosocks5.Server{ |
var server Server |
||||
Addr: Laddr, |
if Websocket { |
||||
SelectMethod: selectMethod, |
server = &WSServer{Addr: Laddr} |
||||
MethodSelected: methodSelected, |
} else { |
||||
Handle: srvHandle, |
server = &Socks5Server{Addr: Laddr} |
||||
} |
} |
||||
log.Fatal(srv.ListenAndServe()) |
log.Fatal(server.ListenAndServe()) |
||||
return |
return |
||||
} |
} |
||||
|
|
||||
|
|||||
@ -0,0 +1,261 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"github.com/ginuerzh/gosocks5" |
||||
|
"github.com/shadowsocks/shadowsocks-go/shadowsocks" |
||||
|
"net" |
||||
|
//"strconv"
|
||||
|
"crypto/tls" |
||||
|
"log" |
||||
|
) |
||||
|
|
||||
|
const ( |
||||
|
rawCert = `-----BEGIN CERTIFICATE----- |
||||
|
MIIC5jCCAdCgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD |
||||
|
bzAeFw0xNDAzMTcwNjIwNTFaFw0xNTAzMTcwNjIwNTFaMBIxEDAOBgNVBAoTB0Fj |
||||
|
bWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccNO1xmd4lWSf |
||||
|
d/0/QS3E93cYIWHw831i/IKxigdRD/XMZonLdEHywW6lOiXazaP8e6CqPGSmnl0x |
||||
|
5k/3dvGCMj2JCVxM6+z7NpL+AiwvXmvkj/TOciCgwqssCwYS2CiVwjfazRjx1ZUJ |
||||
|
VDC5qiyRsfktQ2fVHrpnJGVSRagmiQgwGWBilVG9B8QvRtpQKN/GQGq17oIQm8aK |
||||
|
kOdPt93g93ojMIg7YJpgDgOirvVz/hDn7YD4ryrtPos9CMafFkJprymKpRHyvz7P |
||||
|
8a3+OkuPjFjPnwOHQ5u1U3+8vC44vfb1ExWzDLoT8Xp8Gndx39k0f7MVOol3GnYu |
||||
|
MN/dvNUdAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIAoDATBgNVHSUEDDAKBggrBgEF |
||||
|
BQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDALBgkqhkiG |
||||
|
9w0BAQUDggEBAIG8CJqvTIgJnNOK+i5/IUc/3yF/mSCWuG8qP+Fmo2t6T0PVOtc0 |
||||
|
8wiWH5iWtCAhjn0MRY9l/hIjWm6gUZGHCGuEgsOPpJDYGoNLjH9Xwokm4y3LFNRK |
||||
|
UBrrrDbKRNibApBHCapPf6gC5sXcjOwx7P2/kiHDgY7YH47jfcRhtAPNsM4gjsEO |
||||
|
RmwENY+hRUFHIRfQTyalqND+x6PWhRo3K6hpHs4DQEYPq4P2kFPqUqSBymH+Ny5/ |
||||
|
BcQ3wdMNmC6Bm/oiL1QV0M+/InOsAgQk/EDd0kmoU1ZT2lYHQduGmP099bOlHNpS |
||||
|
uqO3vXF3q8SPPr/A9TqSs7BKkBQbe0+cdsA= |
||||
|
-----END CERTIFICATE-----` |
||||
|
|
||||
|
rawKey = `-----BEGIN RSA PRIVATE KEY----- |
||||
|
MIIEowIBAAKCAQEA3HDTtcZneJVkn3f9P0EtxPd3GCFh8PN9YvyCsYoHUQ/1zGaJ |
||||
|
y3RB8sFupTol2s2j/Hugqjxkpp5dMeZP93bxgjI9iQlcTOvs+zaS/gIsL15r5I/0 |
||||
|
znIgoMKrLAsGEtgolcI32s0Y8dWVCVQwuaoskbH5LUNn1R66ZyRlUkWoJokIMBlg |
||||
|
YpVRvQfEL0baUCjfxkBqte6CEJvGipDnT7fd4Pd6IzCIO2CaYA4Doq71c/4Q5+2A |
||||
|
+K8q7T6LPQjGnxZCaa8piqUR8r8+z/Gt/jpLj4xYz58Dh0ObtVN/vLwuOL329RMV |
||||
|
swy6E/F6fBp3cd/ZNH+zFTqJdxp2LjDf3bzVHQIDAQABAoIBAHal26147nQ+pHwY |
||||
|
jxwers3XDCjWvup7g79lfcqlKi79UiUEA6KYHm7UogMYewt7p4nb2KwH+XycvDiB |
||||
|
aAUf5flXpTs+6IkWauUDiLZi4PlV7uiEexUq5FjirlL0U/6MjbudX4bK4WQ4uxDc |
||||
|
WaV07Kw2iJFOOHLDKT0en9JaX5jtJNc4ZnE9efFoQ5jfypPWtRw65G1rULEg6nvc |
||||
|
GDh+1ce+4foCkpLRC9c24xAwJONZG6x3UqrSS9qfAsb73nWRQrTfUcO3nhoN8VvL |
||||
|
kL9skn1+S06NyUN0KoEtyRBp+RcpXSsBWAo6qZmo/WqhB/gjzWrxVwn20+yJSm35 |
||||
|
ZsMc6QECgYEA8GS+Mp9xfB2szWHz6YTOO1Uu4lHM1ccZMwS1G+dL0KO3uGAiPdvp |
||||
|
woVot6v6w88t7onXsLo5pgz7SYug0CpkF3K/MRd1Ar4lH7PK7IBQ6rFr9ppVxDbx |
||||
|
AEWRswUoPbKCr7W6HU8LbQHDavsDlEIwc6+DiwnL4BzlKjb7RpgQEz0CgYEA6sB5 |
||||
|
uHvx3Y5FDcGk1n73leQSAcq14l3ZLNpjrs8msoREDil/j5WmuSN58/7PGMiMgHEi |
||||
|
1vLm3H796JmvGr9OBvspOjHyk07ui2/We/j9Hoxm1VWhyi8HkLNDj70HKalTTFMz |
||||
|
RHO4O+0xCva+h9mKZrRMVktXr2jjdFn/0MYIZ2ECgYAIIsC1IeRLWQ3CHbCNlKsO |
||||
|
IwHlMvOFwKk/qsceXKOaOhA7szU1dr3gkXdL0Aw6mEZrrkqYdpUA46uVf54/rU+Z |
||||
|
445I8QxKvXiwK/uQKX+TkdGflPWWIG3jnnch4ejMvb/ihnn4B/bRB6A/fKNQXzUY |
||||
|
lTYUfI5j1VaEKTwz1W2l2QKBgByFCcSp+jZqhGUpc3dDsZyaOr3Q/Mvlju7uEVI5 |
||||
|
hIAHpaT60a6GBd1UPAqymEJwivFHzW3D0NxU6VAK68UaHMaoWNfjHY9b9YsnKS2i |
||||
|
kE3XzN56Ks+/avHfdYPO+UHMenw5V28nh+hv5pdoZrlmanQTz3pkaOC8o3WNQZEB |
||||
|
nh/BAoGBAMY5z2f1pmMhrvtPDSlEVjgjELbaInxFaxPLR4Pdyzn83gtIIU14+R8X |
||||
|
2LPs6PPwrNjWnIgrUSVXncIFL3pa45B+Mx1pYCpOAB1+nCZjIBQmpeo4Y0dwA/XH |
||||
|
85EthKPvoszm+OPbyI16OcePV5ocX7lupRYuAo0pek7bomhmHWHz |
||||
|
-----END RSA PRIVATE KEY-----` |
||||
|
) |
||||
|
|
||||
|
var ( |
||||
|
serverConfig = &gosocks5.Config{ |
||||
|
SelectMethod: serverSelectMethod, |
||||
|
MethodSelected: serverMethodSelected, |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
type Socks5Server struct { |
||||
|
Addr string // TCP address to listen on
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
func (s *Socks5Server) ListenAndServe() error { |
||||
|
addr, err := net.ResolveTCPAddr("tcp", s.Addr) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
ln, err := net.ListenTCP("tcp", addr) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
defer ln.Close() |
||||
|
|
||||
|
for { |
||||
|
conn, err := ln.AcceptTCP() |
||||
|
if err != nil { |
||||
|
log.Println("accept:", err) |
||||
|
continue |
||||
|
} |
||||
|
//log.Println("accept", conn.RemoteAddr())
|
||||
|
|
||||
|
go socks5Handle(gosocks5.ServerConn(conn, serverConfig)) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
func serverSelectMethod(methods ...uint8) uint8 { |
||||
|
for _, method := range methods { |
||||
|
if _, ok := Methods[method]; ok { |
||||
|
return method |
||||
|
} |
||||
|
} |
||||
|
return gosocks5.MethodNoAuth |
||||
|
} |
||||
|
|
||||
|
func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) { |
||||
|
switch method { |
||||
|
case MethodTLS: |
||||
|
var cert tls.Certificate |
||||
|
var err error |
||||
|
|
||||
|
if len(CertFile) == 0 || len(KeyFile) == 0 { |
||||
|
cert, err = tls.X509KeyPair([]byte(rawCert), []byte(rawKey)) |
||||
|
} else { |
||||
|
cert, err = tls.LoadX509KeyPair(CertFile, KeyFile) |
||||
|
} |
||||
|
|
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
return nil, err |
||||
|
} |
||||
|
conn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}}) |
||||
|
case MethodAES128, MethodAES192, MethodAES256, |
||||
|
MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable: |
||||
|
cipher, err := shadowsocks.NewCipher(Methods[method], Password) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
conn = shadowsocks.NewConn(conn, cipher) |
||||
|
case gosocks5.MethodNoAcceptable: |
||||
|
return nil, gosocks5.ErrBadMethod |
||||
|
} |
||||
|
|
||||
|
return conn, nil |
||||
|
} |
||||
|
|
||||
|
func socks5Handle(conn net.Conn) { |
||||
|
defer conn.Close() |
||||
|
|
||||
|
req, err := gosocks5.ReadRequest(conn) |
||||
|
if err != nil { |
||||
|
//log.Println(err)
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
switch req.Cmd { |
||||
|
case gosocks5.CmdConnect: |
||||
|
//log.Println("connect", req.Addr.String())
|
||||
|
tconn, err := Connect(req.Addr.String(), Proxy) |
||||
|
if err != nil { |
||||
|
gosocks5.NewReply(gosocks5.HostUnreachable, nil).Write(conn) |
||||
|
return |
||||
|
} |
||||
|
defer tconn.Close() |
||||
|
|
||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, nil) |
||||
|
if err := rep.Write(conn); err != nil { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if err := Transport(conn, tconn); err != nil { |
||||
|
log.Println(err) |
||||
|
} |
||||
|
case gosocks5.CmdBind: |
||||
|
l, err := net.ListenTCP("tcp", nil) |
||||
|
if err != nil { |
||||
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
addr := ToSocksAddr(l.Addr()) |
||||
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) |
||||
|
//log.Println("bind:", addr)
|
||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr) |
||||
|
if err := rep.Write(conn); err != nil { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
tconn, err := l.AcceptTCP() |
||||
|
if err != nil { |
||||
|
log.Println("accept:", err) |
||||
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) |
||||
|
return |
||||
|
} |
||||
|
defer tconn.Close() |
||||
|
l.Close() |
||||
|
|
||||
|
addr = ToSocksAddr(tconn.RemoteAddr()) |
||||
|
log.Println("accept peer:", addr.String()) |
||||
|
rep = gosocks5.NewReply(gosocks5.Succeeded, addr) |
||||
|
if err := rep.Write(conn); err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if err := Transport(conn, tconn); err != nil { |
||||
|
log.Println(err) |
||||
|
} |
||||
|
case gosocks5.CmdUdp: |
||||
|
uconn, err := net.ListenUDP("udp", nil) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) |
||||
|
return |
||||
|
} |
||||
|
defer uconn.Close() |
||||
|
|
||||
|
addr := ToSocksAddr(uconn.LocalAddr()) |
||||
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) |
||||
|
//log.Println("udp:", addr)
|
||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr) |
||||
|
if err := rep.Write(conn); err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
srvTunnelUDP(conn, uconn) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) { |
||||
|
go func() { |
||||
|
b := lpool.Take() |
||||
|
defer lpool.put(b) |
||||
|
|
||||
|
for { |
||||
|
n, addr, err := uconn.ReadFromUDP(b) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
udp := gosocks5.NewUDPDatagram( |
||||
|
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) |
||||
|
//log.Println("r", udp.Header)
|
||||
|
if err := udp.Write(conn); err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
}() |
||||
|
|
||||
|
for { |
||||
|
udp, err := gosocks5.ReadUDPDatagram(conn) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
//log.Println("w", udp.Header)
|
||||
|
addr, err := net.ResolveUDPAddr("udp", udp.Header.Addr.String()) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
continue // drop silently
|
||||
|
} |
||||
|
|
||||
|
if _, err := uconn.WriteToUDP(udp.Data, addr); err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gorilla/websocket" |
||||
|
"net/http" |
||||
|
"log" |
||||
|
"time" |
||||
|
"github.com/ginuerzh/gosocks5" |
||||
|
) |
||||
|
|
||||
|
type WSConn struct { |
||||
|
*websocket.Conn |
||||
|
} |
||||
|
|
||||
|
func NewWSConn(conn *websocket.Conn) *WSConn { |
||||
|
c := &WSConn{} |
||||
|
c.Conn = conn |
||||
|
|
||||
|
return c |
||||
|
} |
||||
|
|
||||
|
func (conn *WSConn) Read(b []byte) (n int, err error) { |
||||
|
_, b, err = conn.ReadMessage() |
||||
|
n = len(b) |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
func (conn *WSConn) Write(b []byte) (n int, err error) { |
||||
|
n = len(b) |
||||
|
err = conn.WriteMessage(websocket.BinaryMessage, b) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
func (conn *WSConn) SetDeadline(t time.Time) error { |
||||
|
if err := conn.SetReadDeadline(t); err != nil { |
||||
|
return err |
||||
|
} |
||||
|
return conn.SetWriteDeadline(t) |
||||
|
} |
||||
|
|
||||
|
type WSServer struct { |
||||
|
Addr string |
||||
|
} |
||||
|
|
||||
|
var upgrader = websocket.Upgrader{ |
||||
|
ReadBufferSize: 8192, |
||||
|
WriteBufferSize: 8192, |
||||
|
CheckOrigin: func(r *http.Request) bool{ return true;}, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
func (s *WSServer) handle(w http.ResponseWriter, r *http.Request) { |
||||
|
conn, err := upgrader.Upgrade(w, r, nil) |
||||
|
if err != nil { |
||||
|
log.Println(err) |
||||
|
return |
||||
|
} |
||||
|
defer conn.Close() |
||||
|
|
||||
|
c := NewWSConn(conn) |
||||
|
|
||||
|
socks5Handle(gosocks5.ServerConn(c, serverConfig)) |
||||
|
} |
||||
|
|
||||
|
func (s *WSServer) ListenAndServe() error { |
||||
|
http.HandleFunc("/", s.handle) |
||||
|
return http.ListenAndServe(s.Addr, nil) |
||||
|
} |
||||
Loading…
Reference in new issue