mirror of
https://github.com/slackhq/nebula.git
synced 2026-03-09 16:21:21 -07:00
ssh: add a handshake timeout for SSH handshake to prevent hangs when client blocks (prevent possible DoS in SSH management interface)
This commit is contained in:
parent
51308b845b
commit
5f6bfc56df
1 changed files with 35 additions and 1 deletions
|
|
@ -6,12 +6,17 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/armon/go-radix"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// defaultHandshakeTimeout defines the timeout duration
|
||||
// that should be used for SSH-Handshake
|
||||
var defaultHandshakeTimeout = 10 * time.Second
|
||||
|
||||
type SSHServer struct {
|
||||
config *ssh.ServerConfig
|
||||
l *logrus.Entry
|
||||
|
|
@ -176,7 +181,12 @@ func (s *SSHServer) run() {
|
|||
return
|
||||
}
|
||||
|
||||
conn, chans, reqs, err := ssh.NewServerConn(c, s.config)
|
||||
conn, chans, reqs, err := s.handshakeWithTimeout(c, defaultHandshakeTimeout)
|
||||
if err != nil {
|
||||
s.l.WithField("remoteAddress", c.RemoteAddr()).WithError(err).Warn("failed to handshake")
|
||||
continue
|
||||
}
|
||||
|
||||
fp := ""
|
||||
if conn != nil {
|
||||
fp = conn.Permissions.Extensions["fp"]
|
||||
|
|
@ -216,6 +226,30 @@ func (s *SSHServer) run() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *SSHServer) handshakeWithTimeout(c net.Conn, timeout time.Duration) (*ssh.ServerConn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
|
||||
type connResult struct {
|
||||
conn *ssh.ServerConn
|
||||
chans <-chan ssh.NewChannel
|
||||
reqs <-chan *ssh.Request
|
||||
err error
|
||||
}
|
||||
resultChan := make(chan connResult, 1)
|
||||
|
||||
go func() {
|
||||
conn, chans, reqs, err := ssh.NewServerConn(c, s.config)
|
||||
resultChan <- connResult{conn, chans, reqs, err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-resultChan:
|
||||
return result.conn, result.chans, result.reqs, result.err
|
||||
case <-time.After(timeout):
|
||||
s.l.WithField("remoteAddress", c.RemoteAddr()).Warn("handshake timeout")
|
||||
c.Close()
|
||||
return nil, nil, nil, errors.New("handshake timeout")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SSHServer) Stop() {
|
||||
// Close the listener, this will cause all session to terminate as well, see SSHServer.Run
|
||||
if s.listener != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue