feat: remove secio support

We've had a reliable and enabled by default TLS implementation since
0.4.23 (over a year ago) and turned off SECIO in September of last year.
We might as well remove support entirely in the next release and
encourage users to upgrade their networks.

Noise is faster, anyways.
This commit is contained in:
Steven Allen 2021-02-25 13:17:43 -08:00
parent 6527675401
commit ccc2d23730
13 changed files with 14 additions and 364 deletions

View File

@ -1 +0,0 @@
seccat

View File

@ -1,255 +0,0 @@
// package main provides an implementation of netcat using the secio package.
// This means the channel is encrypted (and MACed).
// It is meant to exercise the spipe package.
// Usage:
// seccat [<local address>] <remote address>
// seccat -l <local address>
//
// Address format is: [host]:port
package main
import (
"context"
"flag"
"fmt"
"io"
"net"
"os"
"os/signal"
"syscall"
logging "github.com/ipfs/go-log"
ci "github.com/libp2p/go-libp2p-core/crypto"
peer "github.com/libp2p/go-libp2p-core/peer"
pstore "github.com/libp2p/go-libp2p-core/peerstore"
pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem"
secio "github.com/libp2p/go-libp2p-secio"
)
var verbose = false
// Usage prints out the usage of this module.
// Assumes flags use go stdlib flag package.
var Usage = func() {
text := `seccat - secure netcat in Go
Usage:
listen: %s [<local address>] <remote address>
dial: %s -l <local address>
Address format is Go's: [host]:port
`
fmt.Fprintf(os.Stderr, text, os.Args[0], os.Args[0])
flag.PrintDefaults()
}
type args struct {
listen bool
verbose bool
debug bool
localAddr string
remoteAddr string
// keyfile string
keybits int
}
func parseArgs() args {
var a args
// setup + parse flags
flag.BoolVar(&a.listen, "listen", false, "listen for connections")
flag.BoolVar(&a.listen, "l", false, "listen for connections (short)")
flag.BoolVar(&a.verbose, "v", true, "verbose")
flag.BoolVar(&a.debug, "debug", false, "debugging")
// flag.StringVar(&a.keyfile, "key", "", "private key file")
flag.IntVar(&a.keybits, "keybits", 2048, "num bits for generating private key")
flag.Usage = Usage
flag.Parse()
osArgs := flag.Args()
if len(osArgs) < 1 {
exit("")
}
if a.verbose {
out("verbose on")
}
if a.listen {
a.localAddr = osArgs[0]
} else {
if len(osArgs) > 1 {
a.localAddr = osArgs[0]
a.remoteAddr = osArgs[1]
} else {
a.remoteAddr = osArgs[0]
}
}
return a
}
func main() {
args := parseArgs()
verbose = args.verbose
if args.debug {
logging.SetDebugLogging()
}
go func() {
// wait until we exit.
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGABRT)
<-sigc
panic("ABORT! ABORT! ABORT!")
}()
if err := connect(args); err != nil {
exit("%s", err)
}
}
func setupPeer(a args) (peer.ID, pstore.Peerstore, error) {
if a.keybits < ci.MinRsaKeyBits {
return "", nil, ci.ErrRsaKeyTooSmall
}
out("generating key pair...")
sk, pk, err := ci.GenerateKeyPair(ci.RSA, a.keybits)
if err != nil {
return "", nil, err
}
p, err := peer.IDFromPublicKey(pk)
if err != nil {
return "", nil, err
}
ps := pstoremem.NewPeerstore()
err = ps.AddPrivKey(p, sk)
if err != nil {
return "", nil, err
}
err = ps.AddPubKey(p, pk)
if err != nil {
return "", nil, err
}
out("local peer id: %s", p)
return p, ps, nil
}
func connect(args args) error {
p, ps, err := setupPeer(args)
if err != nil {
return err
}
var conn net.Conn
if args.listen {
conn, err = Listen(args.localAddr)
} else {
conn, err = Dial(args.localAddr, args.remoteAddr)
}
if err != nil {
return err
}
// log everything that goes through conn
rwc := &logConn{n: "conn", Conn: conn}
// OK, let's setup the channel.
sk := ps.PrivKey(p)
sg, err := secio.New(sk)
if err != nil {
return err
}
sconn, err := sg.SecureInbound(context.TODO(), rwc)
if err != nil {
return err
}
out("remote peer id: %s", sconn.RemotePeer())
netcat(sconn)
return nil
}
// Listen listens and accepts one incoming UDT connection on a given port,
// and pipes all incoming data to os.Stdout.
func Listen(localAddr string) (net.Conn, error) {
l, err := net.Listen("tcp", localAddr)
if err != nil {
return nil, err
}
out("listening at %s", l.Addr())
c, err := l.Accept()
if err != nil {
return nil, err
}
out("accepted connection from %s", c.RemoteAddr())
// done with listener
l.Close()
return c, nil
}
// Dial connects to a remote address and pipes all os.Stdin to the remote end.
// If localAddr is set, uses it to Dial from.
func Dial(localAddr, remoteAddr string) (net.Conn, error) {
var laddr net.Addr
var err error
if localAddr != "" {
laddr, err = net.ResolveTCPAddr("tcp", localAddr)
if err != nil {
return nil, fmt.Errorf("failed to resolve address %s", localAddr)
}
}
if laddr != nil {
out("dialing %s from %s", remoteAddr, laddr)
} else {
out("dialing %s", remoteAddr)
}
d := net.Dialer{LocalAddr: laddr}
c, err := d.Dial("tcp", remoteAddr)
if err != nil {
return nil, err
}
out("connected to %s", c.RemoteAddr())
return c, nil
}
func netcat(c io.ReadWriteCloser) {
out("piping stdio to connection")
done := make(chan struct{}, 2)
go func() {
n, _ := io.Copy(c, os.Stdin)
out("sent %d bytes", n)
done <- struct{}{}
}()
go func() {
n, _ := io.Copy(os.Stdout, c)
out("received %d bytes", n)
done <- struct{}{}
}()
// wait until we exit.
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, notifySignals...)
select {
case <-done:
case <-sigc:
return
}
c.Close()
}

View File

@ -1,8 +0,0 @@
package main
import (
"os"
"syscall"
)
var notifySignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM}

View File

@ -1,10 +0,0 @@
// +build !plan9
package main
import (
"os"
"syscall"
)
var notifySignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT}

View File

@ -1,47 +0,0 @@
package main
import (
"fmt"
"net"
"os"
logging "github.com/ipfs/go-log"
)
var log = logging.Logger("seccat")
func exit(format string, vals ...interface{}) {
if format != "" {
fmt.Fprintf(os.Stderr, "seccat: error: "+format+"\n", vals...)
}
Usage()
os.Exit(1)
}
func out(format string, vals ...interface{}) {
if verbose {
fmt.Fprintf(os.Stderr, "seccat: "+format+"\n", vals...)
}
}
type logConn struct {
net.Conn
n string
}
func (r *logConn) Read(buf []byte) (int, error) {
n, err := r.Conn.Read(buf)
if n > 0 {
log.Debugf("%s read: %v", r.n, buf)
}
return n, err
}
func (r *logConn) Write(buf []byte) (int, error) {
log.Debugf("%s write: %v", r.n, buf)
return r.Conn.Write(buf)
}
func (r *logConn) Close() error {
return r.Conn.Close()
}

View File

@ -4,10 +4,14 @@ import (
config "github.com/ipfs/go-ipfs-config"
"github.com/libp2p/go-libp2p"
noise "github.com/libp2p/go-libp2p-noise"
secio "github.com/libp2p/go-libp2p-secio"
tls "github.com/libp2p/go-libp2p-tls"
)
const secioEnabledWarning = `The SECIO security transport was enabled in the config but is no longer supported.
SECIO disabled by default in go-ipfs 0.7 removed in go-ipfs 0.9. Please remove
Swarm.Transports.Security.SECIO from your IPFS config.`
func Security(enabled bool, tptConfig config.Transports) interface{} {
if !enabled {
return func() (opts Libp2pOpts) {
@ -18,16 +22,16 @@ func Security(enabled bool, tptConfig config.Transports) interface{} {
}
}
if _, enabled := tptConfig.Security.SECIO.WithDefault(config.Disabled); enabled {
log.Error(secioEnabledWarning)
}
// Using the new config options.
return func() (opts Libp2pOpts) {
opts.Opts = append(opts.Opts, prioritizeOptions([]priorityOption{{
priority: tptConfig.Security.TLS,
defaultPriority: 100,
opt: libp2p.Security(tls.ID, tls.New),
}, {
priority: tptConfig.Security.SECIO,
defaultPriority: config.Disabled,
opt: libp2p.Security(secio.ID, secio.New),
}, {
priority: tptConfig.Security.Noise,
defaultPriority: 300,

View File

@ -1352,8 +1352,7 @@ receiver supports. When establishing an _inbound_ connection, go-ipfs will let
the initiator choose the protocol, but will refuse to use any of the disabled
transports.
Supported transports are: TLS (priority 100), SECIO (Disabled: i.e. priority false), Noise
(priority 300).
Supported transports are: TLS (priority 100) and Noise (priority 300).
No default priority will ever be less than 100.
@ -1369,14 +1368,7 @@ Type: `priority`
#### `Swarm.Transports.Security.SECIO`
[SECIO](https://github.com/libp2p/specs/tree/master/secio) was the most widely
supported IPFS & libp2p security transport. However, it is currently being
phased out in favor of more popular and better vetted protocols like TLS and
Noise.
Default: `false`
Type: `priority`
Support for SECIO has been removed. Please remove this option from your config.
#### `Swarm.Transports.Security.Noise`

View File

@ -544,26 +544,6 @@ ipfs config --json Experimental.GraphsyncEnabled true
### State
Experimental, enabled by default
Stable, enabled by default
[Noise](https://github.com/libp2p/specs/tree/master/noise) libp2p transport based on the [Noise Protocol Framework](https://noiseprotocol.org/noise.html). While TLS remains the default transport in go-ipfs, Noise is easier to implement and will thus serve as the "interop" transport between IPFS and libp2p implementations, eventually replacing SECIO.
### How to enable
While the Noise transport is now shipped and enabled by default in go-ipfs, it won't be used by default for most connections because TLS and SECIO are currently preferred. If you'd like to test out the Noise transport, you can increase the priority of the noise transport:
```
ipfs config --json Swarm.Transports.Security.Noise 1
```
Or even disable TLS and/or SECIO (not recommended for the moment):
```
ipfs config --json Swarm.Transports.Security.TLS false
ipfs config --json Swarm.Transports.Security.SECIO false
```
### Road to being a real feature
- [ ] Needs real-world testing.
- [ ] Ideally a js-ipfs and a rust-ipfs release would include support for Noise.
[Noise](https://github.com/libp2p/specs/tree/master/noise) libp2p transport based on the [Noise Protocol Framework](https://noiseprotocol.org/noise.html). While TLS remains the default transport in go-ipfs, Noise is easier to implement and is thus the "interop" transport between IPFS and libp2p implementations.

1
go.mod
View File

@ -78,7 +78,6 @@ require (
github.com/libp2p/go-libp2p-quic-transport v0.10.0
github.com/libp2p/go-libp2p-record v0.1.3
github.com/libp2p/go-libp2p-routing-helpers v0.2.3
github.com/libp2p/go-libp2p-secio v0.2.2
github.com/libp2p/go-libp2p-swarm v0.4.0
github.com/libp2p/go-libp2p-testing v0.4.0
github.com/libp2p/go-libp2p-tls v0.1.3

1
go.sum
View File

@ -638,7 +638,6 @@ github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVp
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8=
github.com/libp2p/go-libp2p-secio v0.2.2 h1:rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg=
github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY=
github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=

View File

@ -19,7 +19,6 @@ apiaddr=$API_ADDR
# Odd. this fails here, but the inverse works on t0060-daemon.
test_expect_success SOCAT 'transport should be unencrypted ( needs socat )' '
socat - tcp:localhost:$SWARM_PORT,connect-timeout=1 > swarmnc < ../t0060-data/mss-ls &&
grep -q -v "/secio" swarmnc &&
grep -q "/plaintext" swarmnc ||
test_fsh cat swarmnc
'

View File

@ -119,8 +119,7 @@ test_expect_success "re-enable yamux" '
echo "Running advanced tests with NOISE"
test_expect_success "use noise only" '
iptb run -- ipfs config --json Swarm.Transports.Security.TLS false &&
iptb run -- ipfs config --json Swarm.Transports.Security.Secio false
iptb run -- ipfs config --json Swarm.Transports.Security.TLS false
'
run_advanced_test

View File

@ -15,7 +15,6 @@ tcp_addr='"[\"/ip4/127.0.0.1/tcp/0\"]"'
test_expect_success "configure security transports" '
iptb run <<CMDS
[0,1] -- ipfs config --json Swarm.Transports.Security.TLS false &&
[0,1] -- ipfs config --json Swarm.Transports.Security.SECIO false &&
2 -- ipfs config --json Swarm.Transports.Security.Noise false &&
-- ipfs config --json Addresses.Swarm '${tcp_addr}'
CMDS