Add a --protocol-min-version option to router

To allow users to forgo compatibility with Weave Net 1.0 in order to
avoid #912, by setting --protocol-min-version=2.
Defaults to --protocol-min-version=1, i.e. compatible but vulnerable.
This commit is contained in:
David Wragg committed 2015-07-09 14:38:06 +01:00
1 parent 882f14d50c
commit 14d346db8b
5 files changed
+77 -65

No files matched your search

+25 -18
View File
@@ -32,28 +32,30 @@ func main() {
runtime.GOMAXPROCS(procs)
var (
config weave.Config
justVersion bool
ifaceName string
routerName string
nickName string
password string
wait int
pktdebug bool
logLevel string
prof string
bufSzMB int
noDiscovery bool
httpAddr string
iprangeCIDR string
ipsubnetCIDR string
peerCount int
apiPath string
peers []string
config weave.Config
justVersion bool
protocolMinVersion int
ifaceName string
routerName string
nickName string
password string
wait int
pktdebug bool
logLevel string
prof string
bufSzMB int
noDiscovery bool
httpAddr string
iprangeCIDR string
ipsubnetCIDR string
peerCount int
apiPath string
peers []string
)
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
mflag.IntVar(&config.Port, []string{"#port", "-port"}, weave.Port, "router port")
mflag.IntVar(&protocolMinVersion, []string{"-min-protocol-version"}, weave.ProtocolMinVersion, "minimum weave protocol version")
mflag.StringVar(&ifaceName, []string{"#iface", "-iface"}, "", "name of interface to capture/inject from (disabled if blank)")
mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)")
mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)")
@@ -82,6 +84,11 @@ func main() {
Log.Println("Command line options:", options())
Log.Println("Command line peers:", peers)
if protocolMinVersion < weave.ProtocolMinVersion || protocolMinVersion > weave.ProtocolMaxVersion {
Log.Fatalf("--min-protocol-version must be in range [%d,%d]", weave.ProtocolMinVersion, weave.ProtocolMaxVersion)
}
config.ProtocolMinVersion = byte(protocolMinVersion)
var err error
if ifaceName != "" {
+6 -4
View File
@@ -285,10 +285,12 @@ func (conn *LocalConnection) run(actionChan <-chan ConnectionAction, finished ch
conn.TCPConn.SetLinger(0)
intro, err := ProtocolIntroParams{
Features: conn.makeFeatures(),
Conn: conn.TCPConn,
Password: conn.Router.Password,
Outbound: conn.outbound,
MinVersion: conn.Router.ProtocolMinVersion,
MaxVersion: ProtocolMaxVersion,
Features: conn.makeFeatures(),
Conn: conn.TCPConn,
Password: conn.Router.Password,
Outbound: conn.outbound,
}.DoIntro()
if err != nil {
return
+22 -24
View File
@@ -10,9 +10,9 @@ import (
)
const (
Protocol = "weave"
ProtocolMinVersion byte = 1
ProtocolVersion byte = 2
Protocol = "weave"
ProtocolMinVersion = 1
ProtocolMaxVersion = 2
)
var (
@@ -48,10 +48,12 @@ type ProtocolIntroConn interface {
}
type ProtocolIntroParams struct {
Features map[string]string
Conn ProtocolIntroConn
Password []byte
Outbound bool
MinVersion byte
MaxVersion byte
Features map[string]string
Conn ProtocolIntroConn
Password []byte
Outbound bool
}
type ProtocolIntroResults struct {
@@ -63,15 +65,11 @@ type ProtocolIntroResults struct {
}
func (params ProtocolIntroParams) DoIntro() (res ProtocolIntroResults, err error) {
return params.doIntro(ProtocolVersion)
}
func (params ProtocolIntroParams) doIntro(maxVersion byte) (res ProtocolIntroResults, err error) {
if err = params.Conn.SetDeadline(time.Now().Add(HeaderTimeout)); err != nil {
return
}
if res.Version, err = params.exchangeProtocolHeader(maxVersion); err != nil {
if res.Version, err = params.exchangeProtocolHeader(); err != nil {
return
}
@@ -101,12 +99,12 @@ func (params ProtocolIntroParams) doIntro(maxVersion byte) (res ProtocolIntroRes
return
}
func (params ProtocolIntroParams) exchangeProtocolHeader(maxVersion byte) (byte, error) {
func (params ProtocolIntroParams) exchangeProtocolHeader() (byte, error) {
// Write in a separate goroutine to avoid the possibility of
// deadlock. The result channel is of size 1 so that the
// goroutine does not linger even if we encounter an error on
// the read side.
sendHeader := append(ProtocolBytes, ProtocolMinVersion, maxVersion)
sendHeader := append(ProtocolBytes, params.MinVersion, params.MaxVersion)
writeDone := make(chan error, 1)
go func() {
_, err := params.Conn.Write(sendHeader)
@@ -127,27 +125,27 @@ func (params ProtocolIntroParams) exchangeProtocolHeader(maxVersion byte) (byte,
theirMinVersion := header[len(ProtocolBytes)]
minVersion := theirMinVersion
if ProtocolMinVersion > minVersion {
minVersion = ProtocolMinVersion
if params.MinVersion > minVersion {
minVersion = params.MinVersion
}
theirVersion := header[len(ProtocolBytes)+1]
version := theirVersion
if version > maxVersion {
version = maxVersion
theirMaxVersion := header[len(ProtocolBytes)+1]
maxVersion := theirMaxVersion
if maxVersion > params.MaxVersion {
maxVersion = params.MaxVersion
}
if minVersion > version {
if minVersion > maxVersion {
return 0, fmt.Errorf("remote version range [%d,%d] is incompatible with ours [%d,%d]",
theirMinVersion, theirVersion,
ProtocolMinVersion, maxVersion)
theirMinVersion, theirMaxVersion,
params.MinVersion, params.MaxVersion)
}
if err := <-writeDone; err != nil {
return 0, err
}
return version, nil
return maxVersion, nil
}
// The V1 procotol consists of the protocol identification/version
+16 -12
View File
@@ -33,10 +33,10 @@ func connPair() (ProtocolIntroConn, ProtocolIntroConn) {
return &a, &b
}
func doIntro(t *testing.T, ver byte, params ProtocolIntroParams) <-chan ProtocolIntroResults {
func doIntro(t *testing.T, params ProtocolIntroParams) <-chan ProtocolIntroResults {
ch := make(chan ProtocolIntroResults, 1)
go func() {
res, err := params.doIntro(ver)
res, err := params.DoIntro()
require.Nil(t, err)
ch <- res
}()
@@ -45,17 +45,21 @@ func doIntro(t *testing.T, ver byte, params ProtocolIntroParams) <-chan Protocol
func doProtocolIntro(t *testing.T, aver, bver byte, password []byte) byte {
aconn, bconn := connPair()
aresch := doIntro(t, aver, ProtocolIntroParams{
Features: map[string]string{"Name": "A"},
Conn: aconn,
Outbound: true,
Password: password,
aresch := doIntro(t, ProtocolIntroParams{
MinVersion: ProtocolMinVersion,
MaxVersion: aver,
Features: map[string]string{"Name": "A"},
Conn: aconn,
Outbound: true,
Password: password,
})
bresch := doIntro(t, bver, ProtocolIntroParams{
Features: map[string]string{"Name": "B"},
Conn: bconn,
Outbound: false,
Password: password,
bresch := doIntro(t, ProtocolIntroParams{
MinVersion: ProtocolMinVersion,
MaxVersion: bver,
Features: map[string]string{"Name": "B"},
Conn: bconn,
Outbound: false,
Password: password,
})
ares := <-aresch
bres := <-bresch
+8 -7
View File
@@ -28,13 +28,14 @@ const (
type LogFrameFunc func(string, []byte, *EthernetDecoder)
type Config struct {
Port int
Iface *net.Interface
Password []byte
ConnLimit int
PeerDiscovery bool
BufSz int
LogFrame LogFrameFunc
Port int
ProtocolMinVersion byte
Iface *net.Interface
Password []byte
ConnLimit int
PeerDiscovery bool
BufSz int
LogFrame LogFrameFunc
}
type Router struct {