Skip to content
Snippets Groups Projects
Commit e52258ed authored by Yawning Angel's avatar Yawning Angel
Browse files

Make establishing outgoing connections the transport's responsibility.

ClientFactories now have a Dial() method instead of a WrapConn()
method, so that it is possible to write something like meek-client
using the obfs4proxy framework.

This breaks the external interface if anyone is using obfs4proxy as
a library, but the new way of doing things is a trivial modification,
to a single routine that shouldn't have been very large to begin with.
parent 69ffcc39
No related branches found
No related tags found
No related merge requests found
......@@ -155,22 +155,13 @@ func clientHandler(f base.ClientFactory, conn net.Conn, proxyURI *url.URL) {
}
dialFn = dialer.Dial
}
remoteConn, err := dialFn("tcp", socksReq.Target) // XXX: Allow UDP?
remote, err := f.Dial("tcp", socksReq.Target, dialFn, args)
if err != nil {
log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(err))
socksReq.Reply(socks5.ErrorToReplyCode(err))
return
}
defer remoteConn.Close()
// Instantiate the client transport method, handshake, and start pushing
// bytes back and forth.
remote, err := f.WrapConn(remoteConn, args)
if err != nil {
log.Errorf("%s(%s) - handshake failed: %s", name, addrStr, log.ElideError(err))
socksReq.Reply(socks5.ReplyGeneralFailure)
return
}
defer remote.Close()
err = socksReq.Reply(socks5.ReplySucceeded)
if err != nil {
log.Errorf("%s(%s) - SOCKS reply failed: %s", name, addrStr, log.ElideError(err))
......
......@@ -35,6 +35,8 @@ import (
"git.torproject.org/pluggable-transports/goptlib.git"
)
type DialFunc func(string, string) (net.Conn, error)
// ClientFactory is the interface that defines the factory for creating
// pluggable transport protocol client instances.
type ClientFactory interface {
......@@ -48,10 +50,10 @@ type ClientFactory interface {
// generation) to be hidden from third parties.
ParseArgs(args *pt.Args) (interface{}, error)
// WrapConn wraps the provided net.Conn with a transport protocol
// implementation, and does whatever is required (eg: handshaking) to get
// the connection to a point where it is ready to relay data.
WrapConn(conn net.Conn, args interface{}) (net.Conn, error)
// Dial creates an outbound net.Conn, and does whatever is required
// (eg: handshaking) to get the connection to the point where it is
// ready to relay data.
Dial(network, address string, dialFn DialFunc, args interface{}) (net.Conn, error)
}
// ServerFactory is the interface that defines the factory for creating
......
......@@ -108,8 +108,16 @@ func (cf *obfs2ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return nil, validateArgs(args)
}
func (cf *obfs2ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
return newObfs2ClientConn(conn)
func (cf *obfs2ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
conn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
if conn, err = newObfs2ClientConn(conn); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
type obfs2ServerFactory struct {
......
......@@ -92,8 +92,16 @@ func (cf *obfs3ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return nil, nil
}
func (cf *obfs3ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
return newObfs3ClientConn(conn)
func (cf *obfs3ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
conn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
if conn, err = newObfs3ClientConn(conn); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
type obfs3ServerFactory struct {
......
......@@ -204,13 +204,21 @@ func (cf *obfs4ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return &obfs4ClientArgs{nodeID, publicKey, sessionKey, iatMode}, nil
}
func (cf *obfs4ClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
func (cf *obfs4ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
// Validate args before bothering to open connection.
ca, ok := args.(*obfs4ClientArgs)
if !ok {
return nil, fmt.Errorf("invalid argument type for args")
}
return newObfs4ClientConn(conn, ca)
conn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
if conn, err = newObfs4ClientConn(conn, ca); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
type obfs4ServerFactory struct {
......
......@@ -76,12 +76,22 @@ func (cf *ssClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
return newClientArgs(args)
}
func (cf *ssClientFactory) WrapConn(conn net.Conn, args interface{}) (net.Conn, error) {
func (cf *ssClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
// Validate args before opening outgoing connection.
ca, ok := args.(*ssClientArgs)
if !ok {
return nil, fmt.Errorf("invalid argument type for args")
}
return newScrambleSuitClientConn(conn, cf.ticketStore, ca)
conn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
if conn, err = newScrambleSuitClientConn(conn, cf.ticketStore, ca); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
var _ base.ClientFactory = (*ssClientFactory)(nil)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment