support HTTP obfuscating tunnel
This commit is contained in:
parent
3c0d5a81c7
commit
08476e8b2a
@ -171,6 +171,8 @@ func initChain() (*gost.Chain, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tr = gost.Obfs4Transporter()
|
tr = gost.Obfs4Transporter()
|
||||||
|
case "ohttp":
|
||||||
|
tr = gost.ObfsHTTPTransporter()
|
||||||
default:
|
default:
|
||||||
tr = gost.TCPTransporter()
|
tr = gost.TCPTransporter()
|
||||||
}
|
}
|
||||||
@ -288,11 +290,6 @@ func serve(chain *gost.Chain) error {
|
|||||||
ln, err = gost.H2Listener(node.Addr, tlsCfg)
|
ln, err = gost.H2Listener(node.Addr, tlsCfg)
|
||||||
case "h2c":
|
case "h2c":
|
||||||
ln, err = gost.H2CListener(node.Addr)
|
ln, err = gost.H2CListener(node.Addr)
|
||||||
case "obfs4":
|
|
||||||
if err = gost.Obfs4Init(node, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ln, err = gost.Obfs4Listener(node.Addr)
|
|
||||||
case "tcp":
|
case "tcp":
|
||||||
ln, err = gost.TCPListener(node.Addr)
|
ln, err = gost.TCPListener(node.Addr)
|
||||||
case "rtcp":
|
case "rtcp":
|
||||||
@ -311,6 +308,13 @@ func serve(chain *gost.Chain) error {
|
|||||||
case "ssu":
|
case "ssu":
|
||||||
ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
|
ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
|
||||||
ln, err = gost.ShadowUDPListener(node.Addr, node.User, time.Duration(ttl)*time.Second)
|
ln, err = gost.ShadowUDPListener(node.Addr, node.User, time.Duration(ttl)*time.Second)
|
||||||
|
case "obfs4":
|
||||||
|
if err = gost.Obfs4Init(node, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ln, err = gost.Obfs4Listener(node.Addr)
|
||||||
|
case "ohttp":
|
||||||
|
ln, err = gost.ObfsHTTPListener(node.Addr)
|
||||||
default:
|
default:
|
||||||
ln, err = gost.TCPListener(node.Addr)
|
ln, err = gost.TCPListener(node.Addr)
|
||||||
}
|
}
|
||||||
|
1
node.go
1
node.go
@ -58,6 +58,7 @@ func ParseNode(s string) (node Node, err error) {
|
|||||||
node.Transport = "tls"
|
node.Transport = "tls"
|
||||||
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
|
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
|
||||||
case "rtcp", "rudp": // rtcp and rudp are for remote port forwarding
|
case "rtcp", "rudp": // rtcp and rudp are for remote port forwarding
|
||||||
|
case "ohttp": // obfs-http
|
||||||
default:
|
default:
|
||||||
node.Transport = "tcp"
|
node.Transport = "tcp"
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,15 @@
|
|||||||
package gost
|
package gost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/go-log/log"
|
"github.com/go-log/log"
|
||||||
|
|
||||||
@ -14,6 +20,129 @@ import (
|
|||||||
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
|
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type obfsHTTPTransporter struct {
|
||||||
|
tcpTransporter
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObfsHTTPTransporter creates a Transporter that is used by HTTP obfuscating tunnel client.
|
||||||
|
func ObfsHTTPTransporter() Transporter {
|
||||||
|
return &obfsHTTPTransporter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tr *obfsHTTPTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
|
opts := &HandshakeOptions{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
return &obfsHTTPConn{Conn: conn}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type obfsHTTPListener struct {
|
||||||
|
net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObfsHTTPListener creates a Listener for HTTP obfuscating tunnel server.
|
||||||
|
func ObfsHTTPListener(addr string) (Listener, error) {
|
||||||
|
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ln, err := net.ListenTCP("tcp", laddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &obfsHTTPListener{Listener: tcpKeepAliveListener{ln}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *obfsHTTPListener) Accept() (net.Conn, error) {
|
||||||
|
conn, err := l.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obfsHTTPConn{Conn: conn, isServer: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type obfsHTTPConn struct {
|
||||||
|
net.Conn
|
||||||
|
r *http.Request
|
||||||
|
isServer bool
|
||||||
|
handshaked bool
|
||||||
|
handshakeMutex sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *obfsHTTPConn) Handshake() (err error) {
|
||||||
|
c.handshakeMutex.Lock()
|
||||||
|
defer c.handshakeMutex.Unlock()
|
||||||
|
|
||||||
|
if c.handshaked {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.isServer {
|
||||||
|
c.r, err = http.ReadRequest(bufio.NewReader(c.Conn))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
dump, _ := httputil.DumpRequest(c.r, false)
|
||||||
|
log.Logf("[ohttp] %s -> %s\n%s", c.Conn.RemoteAddr(), c.Conn.LocalAddr(), string(dump))
|
||||||
|
}
|
||||||
|
b := bytes.NewBufferString("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
|
||||||
|
if Debug {
|
||||||
|
log.Logf("[ohttp] %s <- %s\n%s", c.Conn.RemoteAddr(), c.Conn.LocalAddr(), b.String())
|
||||||
|
}
|
||||||
|
if _, err = b.WriteTo(c.Conn); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
r := c.r
|
||||||
|
if r == nil {
|
||||||
|
r, err = http.NewRequest(http.MethodPost, "http://www.baidu.com/", nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.Header.Set("User-Agent", DefaultUserAgent)
|
||||||
|
}
|
||||||
|
if err = r.Write(c.Conn); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
|
log.Logf("[ohttp] %s -> %s\n%s", c.Conn.LocalAddr(), c.Conn.RemoteAddr(), string(dump))
|
||||||
|
}
|
||||||
|
var resp *http.Response
|
||||||
|
resp, err = http.ReadResponse(bufio.NewReader(c.Conn), r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
dump, _ := httputil.DumpResponse(resp, false)
|
||||||
|
log.Logf("[ohttp] %s <- %s\n%s", c.Conn.LocalAddr(), c.Conn.RemoteAddr(), string(dump))
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.handshaked = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *obfsHTTPConn) Read(b []byte) (n int, err error) {
|
||||||
|
if err = c.Handshake(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return c.Conn.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *obfsHTTPConn) Write(b []byte) (n int, err error) {
|
||||||
|
if err = c.Handshake(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return c.Conn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
type obfs4Context struct {
|
type obfs4Context struct {
|
||||||
cf base.ClientFactory
|
cf base.ClientFactory
|
||||||
cargs interface{} // type obfs4ClientArgs
|
cargs interface{} // type obfs4ClientArgs
|
1
tls.go
1
tls.go
@ -12,7 +12,6 @@ type tlsTransporter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
||||||
// It accepts a TLS config for TLS handshake.
|
|
||||||
func TLSTransporter() Transporter {
|
func TLSTransporter() Transporter {
|
||||||
return &tlsTransporter{}
|
return &tlsTransporter{}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user