Let proxy pass down EOF (FIN) to the other end.
This PR improves proxy() implementation so that it passes down EOF (i.e. TCP FIN) from the read end to the write end by using TCPConn.CloseWrite(). This is a must for TCP proxy as TCP sockets can be half-closed. Moreover, Server.handleConnect() should wait for two acks from errCh to guarantee that the communication is completely over. This is also fixed. Lastly, noisy debug log is removed.logger
parent
8a8737ba34
commit
66ca0497df
31
request.go
31
request.go
|
@ -3,10 +3,8 @@ package socks5
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -183,14 +181,18 @@ func (s *Server) handleConnect(conn conn, req *Request) error {
|
||||||
|
|
||||||
// Start proxying
|
// Start proxying
|
||||||
errCh := make(chan error, 2)
|
errCh := make(chan error, 2)
|
||||||
go proxy("target", target, req.bufConn, errCh, s.config.Logger)
|
go proxy(target, req.bufConn, errCh)
|
||||||
go proxy("client", conn, target, errCh, s.config.Logger)
|
go proxy(conn, target, errCh)
|
||||||
|
|
||||||
// Wait
|
// Wait
|
||||||
select {
|
for i := 0; i < 2; i++ {
|
||||||
case e := <-errCh:
|
e := <-errCh
|
||||||
return e
|
if e != nil {
|
||||||
|
// return from this function closes target (and conn).
|
||||||
|
return e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleBind is used to handle a connect command
|
// handleBind is used to handle a connect command
|
||||||
|
@ -327,15 +329,10 @@ func sendReply(w io.Writer, resp uint8, addr *AddrSpec) error {
|
||||||
|
|
||||||
// proxy is used to suffle data from src to destination, and sends errors
|
// proxy is used to suffle data from src to destination, and sends errors
|
||||||
// down a dedicated channel
|
// down a dedicated channel
|
||||||
func proxy(name string, dst io.Writer, src io.Reader, errCh chan error, logger *log.Logger) {
|
func proxy(dst io.Writer, src io.Reader, errCh chan error) {
|
||||||
// Copy
|
_, err := io.Copy(dst, src)
|
||||||
n, err := io.Copy(dst, src)
|
if tcpConn, ok := dst.(*net.TCPConn); ok {
|
||||||
|
tcpConn.CloseWrite()
|
||||||
// Log, and sleep. This is jank but allows the otherside
|
}
|
||||||
// to finish a pending copy
|
|
||||||
logger.Printf("[DEBUG] socks: Copied %d bytes to %s", n, name)
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
|
|
||||||
// Send any errors
|
|
||||||
errCh <- err
|
errCh <- err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue