m/pkg/socksproxy: fix fd leak

Change-Id: I4e5f9e937b85a46a9c4ee2e79f4bdcea06858d59
Reviewed-on: https://review.monogon.dev/c/monogon/+/1386
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/pkg/socksproxy/socksproxy.go b/metropolis/pkg/socksproxy/socksproxy.go
index ce35cec..dfd32c4 100644
--- a/metropolis/pkg/socksproxy/socksproxy.go
+++ b/metropolis/pkg/socksproxy/socksproxy.go
@@ -59,9 +59,9 @@
 	// default value (ReplySucceeded).
 	Error Reply
 
-	// Backend is the ReadWriter that will be bridged over to the connecting client
-	// if no Error is set.
-	Backend io.ReadWriter
+	// Backend is the ReadWriteCloser that will be bridged over to the connecting
+	// client if no Error is set.
+	Backend io.ReadWriteCloser
 	// LocalAddress is the IP address that is returned to the client as the local
 	// address of the newly established backend connection.
 	LocalAddress net.IP
@@ -213,6 +213,10 @@
 	}
 
 	// Pipe returned backend into connection.
-	go io.Copy(conRes.Backend, con)
+	go func() {
+		io.Copy(conRes.Backend, con)
+		conRes.Backend.Close()
+	}()
 	io.Copy(con, conRes.Backend)
+	conRes.Backend.Close()
 }
diff --git a/metropolis/test/nanoswitch/socks.go b/metropolis/test/nanoswitch/socks.go
index 7b0278a..3ca8e34 100644
--- a/metropolis/test/nanoswitch/socks.go
+++ b/metropolis/test/nanoswitch/socks.go
@@ -49,6 +49,7 @@
 	res, err := socksproxy.ConnectResponseFromConn(con)
 	if err != nil {
 		logger.Warningf("Connect %s: could not make SOCKS response: %v", target, err)
+		con.Close()
 		return &socksproxy.ConnectResponse{
 			Error: socksproxy.ReplyGeneralFailure,
 		}