add ssh timeout and ip prefix filter

This commit is contained in:
Martin/Geno 2018-07-24 15:07:11 +02:00
parent 0a9c10666a
commit f631ac057b
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
10 changed files with 69 additions and 17 deletions

View File

@ -7,6 +7,8 @@ secret = "passw0rd"
ssh_key = "~/.ssh/id_rsa"
ssh_interface = "wlp4s0"
ssh_ipaddress_suffix = "fe80:"
ssh_timeout = "1m"
# enable receiving
yanic_enable = true

View File

@ -44,13 +44,13 @@ func main() {
log.Info("starting...")
sshmanager := ssh.NewManager(config.SSHPrivateKey)
sshmanager := ssh.NewManager(config.SSHPrivateKey, config.SSHTimeout.Duration)
nodes = runtime.NewNodes(config.StatePath, config.SSHInterface, sshmanager)
nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver)
nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater)
nodesYanic := runtimeYanic.NewNodes(&runtimeYanic.NodesConfig{})
db := runtime.NewYanicDB(nodes)
db := runtime.NewYanicDB(nodes, config.SSHIPAddressSuffix)
go nodesSaveWorker.Start()
go nodesUpdateWorker.Start()

View File

@ -22,6 +22,8 @@ type Config struct {
// SSH private key
SSHPrivateKey string `toml:"ssh_key"`
SSHInterface string `toml:"ssh_interface"`
SSHIPAddressSuffix string `toml:"ssh_ipaddress_suffix"`
SSHTimeout duration.Duration `toml:"ssh_timeout"`
// yanic socket
YanicEnable bool `toml:"yanic_enable"`

View File

@ -3,6 +3,7 @@ package runtime
import (
"bytes"
"net"
"strings"
yanicData "github.com/FreifunkBremen/yanic/data"
"github.com/FreifunkBremen/yanic/lib/jsontime"
@ -23,13 +24,16 @@ type Node struct {
} `json:"statistics" mapstructure:"-"`
}
func NewNode(nodeOrigin *yanicRuntime.Node) *Node {
func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
if nodeinfo := nodeOrigin.Nodeinfo; nodeinfo != nil {
node := &Node{
Hostname: nodeinfo.Hostname,
NodeID: nodeinfo.NodeID,
}
for _, ip := range nodeinfo.Network.Addresses {
if !strings.HasPrefix(ip, ipPrefix) {
continue
}
ipAddr := net.ParseIP(ip)
if node.Address == nil || ipAddr.IsGlobalUnicast() {
node.Address = ipAddr

View File

@ -15,7 +15,7 @@ func TestNode(t *testing.T) {
node1 := &yanicRuntime.Node{
Address: &net.UDPAddr{IP: net.ParseIP("ff02::1")},
}
n1 := NewNode(node1)
n1 := NewNode(node1, "")
assert.Nil(n1)
node1.Nodeinfo = &yanicData.NodeInfo{
@ -23,11 +23,11 @@ func TestNode(t *testing.T) {
Wireless: &yanicData.Wireless{},
Location: &yanicData.Location{Altitude: 13},
}
n1 = NewNode(node1)
n1 = NewNode(node1, "")
assert.NotNil(n1)
assert.Equal(float64(13), n1.Location.Altitude)
n2 := NewNode(node1)
n2 := NewNode(node1, "")
assert.True(n2.IsEqual(n1))
node1.Nodeinfo.Owner.Contact = "blub2"

View File

@ -15,16 +15,18 @@ import (
type YanicDB struct {
databaseYanic.Connection
nodes *Nodes
prefix string
}
func NewYanicDB(nodes *Nodes) *YanicDB {
func NewYanicDB(nodes *Nodes, prefix string) *YanicDB {
return &YanicDB{
nodes: nodes,
prefix: prefix,
}
}
func (conn *YanicDB) InsertNode(n *runtimeYanic.Node) {
node := NewNode(n)
node := NewNode(n, conn.prefix)
if node == nil {
return
}

View File

@ -3,6 +3,7 @@ package ssh
import (
"net"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -12,7 +13,7 @@ func TestExecute(t *testing.T) {
addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22}
mgmt := NewManager("~/.ssh/id_rsa")
mgmt := NewManager("~/.ssh/id_rsa", time.Second)
assert.NotNil(mgmt, "no new manager created")
client, err := mgmt.ConnectTo(addr)

View File

@ -16,10 +16,11 @@ type Manager struct {
config *ssh.ClientConfig
clientsBlacklist map[string]time.Time
clientsMUX sync.Mutex
timeout time.Duration
}
// create a new SSH Connection Manager by ssh file
func NewManager(file string) *Manager {
func NewManager(file string, timeout time.Duration) *Manager {
var auths []ssh.AuthMethod
if auth := SSHAgent(); auth != nil {
auths = append(auths, auth)
@ -36,9 +37,34 @@ func NewManager(file string) *Manager {
return &Manager{
config: sshConfig,
clientsBlacklist: make(map[string]time.Time),
timeout: timeout,
}
}
// Conn wraps a net.Conn, and sets a deadline for every read
// and write operation.
type Conn struct {
net.Conn
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func (c *Conn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
func (c *Conn) Write(b []byte) (int, error) {
err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
if err != nil {
return 0, err
}
return c.Conn.Write(b)
}
func (m *Manager) ConnectTo(addr net.TCPAddr) (*ssh.Client, error) {
m.clientsMUX.Lock()
defer m.clientsMUX.Unlock()
@ -50,7 +76,20 @@ func (m *Manager) ConnectTo(addr net.TCPAddr) (*ssh.Client, error) {
}
}
client, err := ssh.Dial("tcp", addr.String(), m.config)
addrString := addr.String()
conn, err := net.DialTimeout("tcp", addrString, m.timeout)
if err != nil {
return nil, err
}
timeoutConn := &Conn{conn, m.timeout, m.timeout}
c, chans, reqs, err := ssh.NewClientConn(timeoutConn, addrString, m.config)
if err != nil {
return nil, err
}
client := ssh.NewClient(c, chans, reqs)
if err != nil {
if strings.Contains(err.Error(), "no supported methods remain") {
m.clientsBlacklist[addr.IP.String()] = time.Now()

View File

@ -3,6 +3,7 @@ package ssh
import (
"net"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -10,7 +11,7 @@ import (
func TestManager(t *testing.T) {
assert := assert.New(t)
mgmt := NewManager("~/.ssh/id_rsa")
mgmt := NewManager("~/.ssh/id_rsa", time.Second)
assert.NotNil(mgmt, "no new manager created")
client, _ := mgmt.ConnectTo(net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22})

View File

@ -4,6 +4,7 @@ import (
"net"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -11,7 +12,7 @@ import (
func TestRun(t *testing.T) {
assert := assert.New(t)
addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22}
mgmt := NewManager("~/.ssh/id_rsa")
mgmt := NewManager("~/.ssh/id_rsa", time.Second)
assert.NotNil(mgmt, "no new manager created")
client, err := mgmt.ConnectTo(addr)