summaryrefslogtreecommitdiff
path: root/listener.go
diff options
context:
space:
mode:
Diffstat (limited to 'listener.go')
-rw-r--r--listener.go82
1 files changed, 82 insertions, 0 deletions
diff --git a/listener.go b/listener.go
new file mode 100644
index 0000000..ae81b19
--- /dev/null
+++ b/listener.go
@@ -0,0 +1,82 @@
+package obfsvpn
+
+import (
+ "bytes"
+ "context"
+ "crypto/rand"
+ "encoding/hex"
+ "net"
+
+ 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"
+)
+
+// ListenConfig contains options for listening to an address.
+// If Seed is not set it defaults to a randomized value.
+// If StateDir is not set the current working directory is used.
+type ListenConfig struct {
+ ListenConfig net.ListenConfig
+
+ NodeID *ntor.NodeID
+ PrivateKey *ntor.PrivateKey
+ Seed [ntor.KeySeedLength]byte
+ StateDir string
+}
+
+// Listen announces on the local network address.
+//
+// See func net.Dial for a description of the network and address parameters.
+func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (*Listener, error) {
+ ln, err := lc.ListenConfig.Listen(ctx, network, address)
+ if err != nil {
+ return nil, err
+ }
+ args := make(pt.Args)
+ args.Add("node-id", lc.NodeID.Hex())
+ args.Add("private-key", lc.PrivateKey.Hex())
+ seed := ntor.KeySeed{}
+ if bytes.Equal(lc.Seed[:], seed[:]) {
+ _, err = rand.Read(seed[:])
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ seed = lc.Seed
+ }
+ args.Add("drbg-seed", hex.EncodeToString(seed[:]))
+ sf, err := (&obfs4.Transport{}).ServerFactory(lc.StateDir, &args)
+ if err != nil {
+ return nil, err
+ }
+ return &Listener{sf: sf, ln: ln}, nil
+}
+
+// Listener is a network listener that accepts obfuscated connections and
+// performs the ntor handshake on them.
+type Listener struct {
+ sf base.ServerFactory
+ ln net.Listener
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *Listener) Accept() (net.Conn, error) {
+ conn, err := l.ln.Accept()
+ if err != nil {
+ return nil, err
+ }
+ conn, err = l.sf.WrapConn(conn)
+ return conn, err
+}
+
+// Close closes the listener.
+// Any blcked Accept operations will be unblocked and return errors.
+func (l *Listener) Close() error {
+ return l.ln.Close()
+}
+
+// Addr returns the listener's network address.
+func (l *Listener) Addr() net.Addr {
+ return l.ln.Addr()
+}