Private Network
1. PNet provides extra encrypt/decrypt to a swarm connection:
Initialization here:
func PrivateNetwork(prot pnet.Protector) Option {
return func(cfg *Config) error {
if cfg.Protector != nil {
return fmt.Errorf("cannot specify multiple private network options")
}
cfg.Protector = prot
return nil
}
}
2. When creating a host, a PNet option has to be provided:
protec, err := pnet.NewProtector(bytes.NewReader(swarmkey))
opts := []libp2p.Option{
libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", listenPort)),
libp2p.Identity(priv),
libp2p.Transport(q),
libp2p.DefaultTransports,
libp2p.DefaultMuxers,
libp2p.DefaultSecurity,
libp2p.NATPortMap(),
libp2p.PrivateNetwork(protec),
}
3. Setup PNet connection
func (u *Upgrader) upgrade(ctx context.Context, t transport.Transport, maconn manet.Conn, p peer.ID) (transport.CapableConn, error) {
if u.Filters != nil && u.Filters.AddrBlocked(maconn.RemoteMultiaddr()) {
log.Debugf("blocked connection from %s", maconn.RemoteMultiaddr())
maconn.Close()
return nil, fmt.Errorf("blocked connection from %s", maconn.RemoteMultiaddr())
}
var conn net.Conn = maconn
if u.Protector != nil {
pconn, err := u.Protector.Protect(conn)
if err != nil {
conn.Close()
return nil, fmt.Errorf("failed to setup private network protector: %s", err)
}
conn = pconn
...
Protect will call newPSKConn to generate pskConn
func newPSKConn(psk *[32]byte, insecure net.Conn) (net.Conn, error) {
if insecure == nil {
return nil, errInsecureNil
}
if psk == nil {
return nil, errPSKNil
}
return &pskConn{
Conn: insecure,
psk: psk,
}, nil
}
type pskConn struct {
net.Conn
psk *[32]byte
writeS20 cipher.Stream
readS20 cipher.Stream
}
conn will be replaced by pconn(pskConn) when Protector is out there
4. CipherStream when reading or writing. salsa20 will be used
func (c *pskConn) Read(out []byte) (int, error) {
if c.readS20 == nil {
nonce := make([]byte, 24)
_, err := io.ReadFull(c.Conn, nonce)
if err != nil {
return 0, errShortNonce
}
c.readS20 = salsa20.New(c.psk, nonce)
}
n, err := c.Conn.Read(out) // read to in
if n > 0 {
c.readS20.XORKeyStream(out[:n], out[:n]) // decrypt to out buffer
}
return n, err
}