add ssh timeout and ip prefix filter
This commit is contained in:
parent
0a9c10666a
commit
f631ac057b
|
@ -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
|
||||
|
|
4
main.go
4
main.go
|
@ -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()
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@ type Config struct {
|
|||
Secret string `toml:"secret"`
|
||||
|
||||
// SSH private key
|
||||
SSHPrivateKey string `toml:"ssh_key"`
|
||||
SSHInterface string `toml:"ssh_interface"`
|
||||
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"`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -14,17 +14,19 @@ import (
|
|||
|
||||
type YanicDB struct {
|
||||
databaseYanic.Connection
|
||||
nodes *Nodes
|
||||
nodes *Nodes
|
||||
prefix string
|
||||
}
|
||||
|
||||
func NewYanicDB(nodes *Nodes) *YanicDB {
|
||||
func NewYanicDB(nodes *Nodes, prefix string) *YanicDB {
|
||||
return &YanicDB{
|
||||
nodes: nodes,
|
||||
nodes: nodes,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
func (conn *YanicDB) InsertNode(n *runtimeYanic.Node) {
|
||||
node := NewNode(n)
|
||||
node := NewNode(n, conn.prefix)
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue