fix: sanity check read EOF in first read phase

This commit is contained in:
SunBK201 2023-12-13 14:48:03 +08:00
parent 4729762bc6
commit b4064d1fb7
24 changed files with 56 additions and 44 deletions

View File

@ -1,10 +1,10 @@
5a75ec8000a8b3593a853c12863e2b46 ./ua3f-0.1.1-386.tar.gz
85cce8bd5d2aef5d8481cfe6f1f9b099 ./ua3f-0.1.1-amd64.tar.gz
4bfe414dd58e2eeb57e3381cbada7a2b ./ua3f-0.1.1-arm.tar.gz
da1d3a054e66d5680a38a3ffcb67862a ./ua3f-0.1.1-arm64.tar.gz
da1d3a054e66d5680a38a3ffcb67862a ./ua3f-0.1.1-armv8.tar.gz
02fe1c3c18115dcecf4bf38f62e5de83 ./ua3f-0.1.1-mips64.tar.gz
69d64e2f443859418f74749e7d02e018 ./ua3f-0.1.1-mipsle-hardfloat.tar.gz
23781cf6da653e6bfd40c91ccb258885 ./ua3f-0.1.1-mipsle-softfloat.tar.gz
41b823964a881b5e2c429e785287e4e4 ./ua3f-0.1.1-mipsle.tar.gz
4319b5e0e69bf2637a33ca6aee3ed284 ./ua3f-0.1.1-riscv64.tar.gz
69348631c2d1bf17768dcbeac972b63f ./ua3f-0.1.2-386.tar.gz
06b14787b948906ce42372ab656d2078 ./ua3f-0.1.2-amd64.tar.gz
b53f3b49d42b4d93800e4665e525f26c ./ua3f-0.1.2-arm.tar.gz
3497c75d7f53085b8d34d148059831f8 ./ua3f-0.1.2-arm64.tar.gz
3497c75d7f53085b8d34d148059831f8 ./ua3f-0.1.2-armv8.tar.gz
7a19c7e1539294b2fe18244bab9ad12e ./ua3f-0.1.2-mips64.tar.gz
8034fb13e48c836793dfbc3f1d213c2f ./ua3f-0.1.2-mipsle-hardfloat.tar.gz
b386e9b12c94413f53bdf7e8bcc232d7 ./ua3f-0.1.2-mipsle-softfloat.tar.gz
8034fb13e48c836793dfbc3f1d213c2f ./ua3f-0.1.2-mipsle.tar.gz
5f6870e9f7b8d4c0e4ffc56eff1c37d4 ./ua3f-0.1.2-riscv64.tar.gz

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/ua3f-0.1.2-386.tar.gz Normal file

Binary file not shown.

BIN
bin/ua3f-0.1.2-amd64.tar.gz Normal file

Binary file not shown.

BIN
bin/ua3f-0.1.2-arm.tar.gz Normal file

Binary file not shown.

BIN
bin/ua3f-0.1.2-arm64.tar.gz Normal file

Binary file not shown.

BIN
bin/ua3f-0.1.2-armv8.tar.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,7 @@
#!/bin/sh
project_name="ua3f"
release_version="0.1.1"
release_version="0.1.2"
target=cmd/ua3f.go
release_dir=./bin

View File

@ -16,7 +16,7 @@ import (
"github.com/sirupsen/logrus"
)
var version = "0.1.1"
var version = "0.1.2"
var payloadByte []byte
var cache *expirable.LRU[string, string]
@ -67,13 +67,13 @@ func process(client net.Conn) {
client.Close()
return
}
target, err := Socks5Connect(client)
target, destAddrPort, err := Socks5Connect(client)
if err != nil {
logrus.Error("Connect failed: ", err)
client.Close()
return
}
Socks5Forward(client, target)
Socks5Forward(client, target, destAddrPort)
}
func Socks5Auth(client net.Conn) (err error) {
@ -97,61 +97,61 @@ func Socks5Auth(client net.Conn) (err error) {
return nil
}
func Socks5Connect(client net.Conn) (net.Conn, error) {
func Socks5Connect(client net.Conn) (net.Conn, string, error) {
buf := make([]byte, 256)
n, err := io.ReadFull(client, buf[:4])
if n != 4 {
return nil, errors.New("read header:" + err.Error())
return nil, "", errors.New("read header:" + err.Error())
}
ver, cmd, _, atyp := buf[0], buf[1], buf[2], buf[3]
if ver != 5 || cmd != 1 {
return nil, errors.New("invalid ver/cmd")
return nil, "", errors.New("invalid ver/cmd")
}
addr := ""
switch atyp {
case 1:
n, err = io.ReadFull(client, buf[:4])
if n != 4 {
return nil, errors.New("invalid IPv4:" + err.Error())
return nil, "", errors.New("invalid IPv4:" + err.Error())
}
addr = fmt.Sprintf("%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3])
case 3:
n, err = io.ReadFull(client, buf[:1])
if n != 1 {
return nil, errors.New("invalid hostname:" + err.Error())
return nil, "", errors.New("invalid hostname:" + err.Error())
}
addrLen := int(buf[0])
n, err = io.ReadFull(client, buf[:addrLen])
if n != addrLen {
return nil, errors.New("invalid hostname:" + err.Error())
return nil, "", errors.New("invalid hostname:" + err.Error())
}
addr = string(buf[:addrLen])
case 4:
return nil, errors.New("IPv6: no supported yet")
return nil, "", errors.New("IPv6: no supported yet")
default:
return nil, errors.New("invalid atyp")
return nil, "", errors.New("invalid atyp")
}
n, err = io.ReadFull(client, buf[:2])
if n != 2 {
return nil, errors.New("read port:" + err.Error())
return nil, "", errors.New("read port:" + err.Error())
}
port := binary.BigEndian.Uint16(buf[:2])
destAddrPort := fmt.Sprintf("%s:%d", addr, port)
logrus.Debug(fmt.Sprintf("Connecting %s", destAddrPort))
dest, err := net.Dial("tcp", destAddrPort)
if err != nil {
return nil, errors.New("dial dst:" + err.Error())
return nil, destAddrPort, errors.New("dial dst:" + err.Error())
}
logrus.Debug(fmt.Sprintf("Connected %s", destAddrPort))
_, err = client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})
if err != nil {
dest.Close()
return nil, errors.New("write rsp:" + err.Error())
return nil, destAddrPort, errors.New("write rsp:" + err.Error())
}
return dest, nil
return dest, destAddrPort, nil
}
func Socks5Forward(client, target net.Conn) {
func Socks5Forward(client, target net.Conn, destAddrPort string) {
forward := func(src, dest net.Conn) {
defer src.Close()
defer dest.Close()
@ -161,22 +161,33 @@ func Socks5Forward(client, target net.Conn) {
gforward := func(dst, src net.Conn) {
defer dst.Close()
defer src.Close()
CopyPileline(dst, src)
CopyPileline(dst, src, destAddrPort)
}
go forward(client, target)
if cache.Contains(string(target.RemoteAddr().String())) {
if cache.Contains(destAddrPort) {
logrus.Debug(fmt.Sprintf("Hit LRU Relay Cache: %s", destAddrPort))
go forward(target, client)
return
}
go gforward(target, client)
}
func CopyPileline(dst io.Writer, src io.Reader) {
func CopyPileline(dst io.Writer, src io.Reader, destAddrPort string) {
buf := make([]byte, 1024*8)
nr, err := src.Read(buf)
if err != nil && err != io.EOF {
logrus.Error("read error: ", err)
if err != nil {
if err == io.EOF {
logrus.Debug(fmt.Sprintf("[%s][%s] read EOF in first phase", destAddrPort, src.(*net.TCPConn).RemoteAddr().String()))
} else if strings.Contains(err.Error(), "use of closed network connection") {
logrus.Debug(fmt.Sprintf("[%s][%s] read closed in first phase: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
} else {
logrus.Error(fmt.Sprintf("[%s][%s] read error in first phase: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
}
return
}
if nr == 0 {
logrus.Debug(fmt.Sprintf("[%s][%s] read 0 in first phase", destAddrPort, src.(*net.TCPConn).RemoteAddr().String()))
return
}
hint := string(buf[0:7])
@ -191,7 +202,8 @@ func CopyPileline(dst io.Writer, src io.Reader) {
if !is_http {
dst.Write(buf[0:nr])
io.Copy(dst, src)
cache.Add(string(dst.(*net.TCPConn).RemoteAddr().String()), string(dst.(*net.TCPConn).RemoteAddr().String()))
cache.Add(destAddrPort, destAddrPort)
logrus.Debug(fmt.Sprintf("Not HTTP, Hint: %v, Add LRU Relay Cache: %s", buf[0:7], destAddrPort))
return
}
for {
@ -201,7 +213,7 @@ func CopyPileline(dst io.Writer, src io.Reader) {
var m int
m, err = src.Read(buf[nr:])
if err != nil {
logrus.Error("read error in http accumulation: ", err)
logrus.Error(fmt.Sprintf("[%s] read error in http accumulation: %v", destAddrPort, err))
break
}
nr += m
@ -209,7 +221,7 @@ func CopyPileline(dst io.Writer, src io.Reader) {
}
value, start, end := parser.FindHeader([]byte("User-Agent"))
if value != nil && end > start {
logrus.Debug(fmt.Sprintf("[%s] Hit User-Agent: %s", string(parser.Host()), string(value)))
logrus.Debug(fmt.Sprintf("[%s][%s] Hit User-Agent: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), string(value)))
for i := start; i < end; i++ {
buf[i] = 32
}
@ -220,10 +232,10 @@ func CopyPileline(dst io.Writer, src io.Reader) {
buf[start+i] = payloadByte[i]
}
} else {
logrus.Debug(fmt.Sprintf("[%s] Not found User-Agent, Add LRU Relay Cache", string(parser.Host())))
logrus.Debug(fmt.Sprintf("[%s] Not found User-Agent, Add LRU Relay Cache", destAddrPort))
dst.Write(buf[0:nr])
io.Copy(dst, src)
cache.Add(string(dst.(*net.TCPConn).RemoteAddr().String()), string(dst.(*net.TCPConn).RemoteAddr().String()))
cache.Add(destAddrPort, destAddrPort)
return
}
bodyLen := int(parser.ContentLength())
@ -233,7 +245,7 @@ func CopyPileline(dst io.Writer, src io.Reader) {
_, ew := dst.Write(buf[0:min(httpBodyOffset+bodyLen, nr)])
if ew != nil {
logrus.Error("write error: ", ew)
logrus.Error(fmt.Sprintf("[%s][%s] write error: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), ew.Error()))
break
}
if httpBodyOffset+bodyLen > nr {
@ -241,12 +253,12 @@ func CopyPileline(dst io.Writer, src io.Reader) {
for left > 0 {
m, err := src.Read(buf[0:left])
if err != nil {
logrus.Error("read error in large body: ", err)
logrus.Error(fmt.Sprintf("[%s][%s] read error in large body: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
break
}
_, ew := dst.Write(buf[0:m])
if ew != nil {
logrus.Error("write error in large body: ", ew)
logrus.Error(fmt.Sprintf("[%s][%s] write error in large body: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), ew.Error()))
break
}
left -= m
@ -263,11 +275,11 @@ func CopyPileline(dst io.Writer, src io.Reader) {
nr += m
if err != nil {
if err == io.EOF {
logrus.Debug("read EOF in next phase")
logrus.Debug(fmt.Sprintf("[%s][%s] read EOF in next phase", destAddrPort, src.(*net.TCPConn).RemoteAddr().String()))
} else if strings.Contains(err.Error(), "use of closed network connection") {
logrus.Debug("read closed in next phase: ", err)
logrus.Debug(fmt.Sprintf("[%s][%s] read closed in next phase: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
} else {
logrus.Error("read error in next phase: ", err)
logrus.Error(fmt.Sprintf("[%s][%s] read error in next phase: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
}
break
}

View File

@ -16,7 +16,7 @@ getcpucore() {
cd /root
getcpucore
version=0.1.1
version=0.1.2
ua3f_tar=ua3f-$version-$cpucore.tar.gz
if id -u shellclash &> /dev/null; then