1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
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
}
// NewListenConfigCert creates a listener config by unpacking the node ID from
// its certificate.
// The private key must still be specified.
func NewListenConfigCert(cert string) (*ListenConfig, error) {
nodeID, _, err := unpackCert(cert)
if err != nil {
return nil, err
}
return &ListenConfig{
NodeID: nodeID,
}, nil
}
// Wrap takes an existing net.Listener and wraps it in a listener that is
// configured to perform the ntor handshake.
// Values from the inner net.ListenConfig are ignored.
func (lc *ListenConfig) Wrap(ctx context.Context, ln net.Listener) (*Listener, error) {
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
}
// 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
}
return lc.Wrap(ctx, ln)
}
// 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 blocked 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()
}
|