在Go中设置idletimeout



我在go中有一个函数,它处理通过tcp和ssh处理的连接。我试图通过在连接函数中创建结构来设置空闲超时。

用例-客户应该能够建立连接并上传/下载多个文件

参考-tcp服务器中的IdleTimeout

功能代码:

type Conn struct {
net.Conn
idleTimeout time.Duration
}
func HandleConn(conn net.Conn) {
var err error
rAddr := conn.RemoteAddr()
session := shortuuid.New()
config := LoadSSHServerConfig(session)

blocklistItem := blocklist.GetBlockListItem(rAddr)
if blocklistItem.IsBlocked() {
conn.Close()
atomic.AddInt64(&stats.Stats.BlockedConnections, 1)
return
}

func (c *Conn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.idleTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
sConn, chans, reqs, err := ssh.NewServerConn(conn, config)
if err != nil {
if err == io.EOF {
log.Errorw("SSH: Handshaking was terminated", log.Fields{
"address": rAddr,
"error":   err,
"session": session})
} else {
log.Errorw("SSH: Error on handshaking", log.Fields{
"address": rAddr,
"error":   err,
"session": session})
}
atomic.AddInt64(&stats.Stats.AuthorizationFailed, 1)
return
}
log.Infow("connection accepted", log.Fields{
"user": sConn.User(),
})
if user, ok := users[session]; ok {
log.Infow("SSH: Connection accepted", log.Fields{
"user":          user.LogFields(),
"clientVersion": string(sConn.ClientVersion())})
atomic.AddInt64(&stats.Stats.AuthorizationSucceeded, 1)

// The incoming Request channel must be serviced.
go ssh.DiscardRequests(reqs)
// Key ID: sConn.Permissions.Extensions["key-id"]
handleServerConn(user, chans)
log.Infow("connection finished", log.Fields{"user": user.LogFields()})

log.Infow("checking connections", log.Fields{
//"cc":          Stats.AcceptedConnections,
"cc2": &stats.Stats.AcceptedConnections})
// Remove connection from local cache
delete(users, session)
} else {
log.Infow("user not found from memory", log.Fields{"username": sConn.User()})
}
}

此代码来自侦听功能:

func Listen() {

listener, err := net.Listen("tcp", sshListen)
if err != nil {
panic(err)
}

if useProxyProtocol {
listener = &proxyproto.Listener{
Listener:           listener,
ProxyHeaderTimeout: time.Second * 10,
}
}

for {
// Once a ServerConfig has been configured, connections can be accepted.
conn, err := listener.Accept()
if err != nil {
log.Errorw("SSH: Error accepting incoming connection", log.Fields{"error": err})
atomic.AddInt64(&stats.Stats.FailedConnections, 1)
continue
}

// Before use, a handshake must be performed on the incoming net.Conn.
// It must be handled in a separate goroutine,
// otherwise one user could easily block entire loop.
// For example, user could be asked to trust server key fingerprint and hangs.
go HandleConn(conn)
}
}

是否可以只为空闲20秒的连接设置截止日期(无上传/下载(。

编辑1:根据@LiamKelly的建议,我对代码进行了更改。现在代码就像

type SshProxyConn struct {
net.Conn
idleTimeout time.Duration
}
func (c *SshProxyConn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.idleTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
func HandleConn(conn net.Conn) {
//lines of code as above
sshproxyconn := &SshProxyConn{nil, time.Second * 20}
Conn, chans, reqs, err := ssh.NewServerConn(sshproxyconn, config)
//lines of code
}

但现在的问题是SSH没有发生。我得到了错误";连接关闭";当我尝试执行ssh时。它还在等待";conn";函数调用中的变量?

是否可以只为空闲20秒的连接设置最后期限

好的,首先是一个一般的免责声明,我假设go-protoproxy实现了我们预期的Conn接口。同样正如您之前所暗示的,我认为您不能将struct方法放在另一个函数中(我还建议将其重命名为唯一的方法,以防止Connnet.Conn混淆(。

type SshProxyConn struct {
net.Conn
idleTimeout time.Duration
}
func (c *SshProxyConn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.idleTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}

func HandleConn(conn net.Conn) {

这就更加清楚了您的主要问题是什么,即您将普通的net.Conn传递给了SSH服务器,而不是包装器类。所以

sConn, chans, reqs, err := ssh.NewServerConn(conn, config)

编辑

sshproxyconn := &SshProxyConn{conn, time.Second * 20}
Conn, chans, reqs, err := ssh.NewServerConn(sshproxyconn , config)

最新更新