fix: avoid closing proxy relay listener before validating remote source

This commit is contained in:
2026-07-29 12:47:35 +01:00
parent 3363ac9dad
commit 8fcda63742
+27 -14
View File
@@ -6,6 +6,7 @@ import (
"io"
"log"
"net"
"os"
"sync"
"time"
@@ -86,22 +87,34 @@ func (s *Session) Serve(stream AgentStream) error {
_ = l.SetDeadline(time.Now().Add(s.timeout))
}
conn, err := s.listener.Accept()
if err != nil {
s.setReason("guacd_timeout")
return fmt.Errorf("waiting for guacd: %w", err)
}
// One connection only: nothing else may claim this port.
s.Close("")
// Accept until a connection from an allowed source arrives or the
// rendezvous deadline (set once, above) expires. A rejected connection is
// closed and the loop retries within the same deadline; the listener is
// only closed once we have a valid connection, the deadline expires, or
// Accept fails for a genuine (non-timeout) reason.
for {
conn, err := s.listener.Accept()
if err != nil {
var netErr net.Error
if errors.Is(err, os.ErrDeadlineExceeded) || (errors.As(err, &netErr) && netErr.Timeout()) {
s.setReason("guacd_timeout")
} else {
s.setReason("accept_failed")
}
return fmt.Errorf("waiting for guacd: %w", err)
}
if !allowedRemote(conn.RemoteAddr().String(), s.allowed) {
_ = conn.Close()
s.setReason("foreign_source")
return fmt.Errorf("relay connection from disallowed source %s", conn.RemoteAddr())
}
defer conn.Close()
if !allowedRemote(conn.RemoteAddr().String(), s.allowed) {
_ = conn.Close()
continue
}
return s.relay(conn, stream)
// One connection only: nothing else may claim this port.
s.Close("")
defer conn.Close()
return s.relay(conn, stream)
}
}
func (s *Session) relay(conn net.Conn, stream AgentStream) error {