package obfsvpn import ( "context" "net" "strconv" pt "git.torproject.org/pluggable-transports/goptlib.git" "gitlab.com/yawning/obfs4.git/common/ntor" "gitlab.com/yawning/obfs4.git/transports/base" "gitlab.com/yawning/obfs4.git/transports/obfs4" ) // IATMode determines the amount of time sent between packets. type IATMode int // Valid IAT modes. const ( IATNone IATMode = iota IATEnabled IATParanoid ) // Dialer contains options for connecting to an address and obfuscating traffic // with the obfs4 protocol. // It performs the ntor handshake on all dialed connections. type Dialer struct { Dialer net.Dialer NodeID *ntor.NodeID PublicKey *ntor.PublicKey IATMode IATMode cf base.ClientFactory } // Dial creates an outbound net.Conn and performs the ntor handshake. func (d *Dialer) Dial(ctx context.Context, network, address string) (net.Conn, error) { if d.cf == nil { cf, err := (&obfs4.Transport{}).ClientFactory("") if err != nil { return nil, err } d.cf = cf } ptArgs := make(pt.Args) ptArgs.Add("node-id", d.NodeID.Hex()) ptArgs.Add("public-key", d.PublicKey.Hex()) ptArgs.Add("iat-mode", strconv.Itoa(int(d.IATMode))) args, err := d.cf.ParseArgs(&ptArgs) if err != nil { return nil, err } return d.cf.Dial(network, address, func(network, address string) (net.Conn, error) { return d.Dialer.DialContext(ctx, network, address) }, args) }