V13
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"crypto/subtle"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"dragontcp/internal/protocol"
|
||||
"dragontcp/internal/wire"
|
||||
)
|
||||
|
||||
var active int64
|
||||
@@ -159,9 +159,9 @@ func handle(
|
||||
cache *dnsCache,
|
||||
tcpBuffer int,
|
||||
slots chan struct{},
|
||||
manager *chunkManager,
|
||||
manager *streamManager,
|
||||
chunkMax int,
|
||||
chunkBuffered int,
|
||||
bufferBytes int,
|
||||
chunkPollWait time.Duration,
|
||||
debug *serverDebug,
|
||||
) {
|
||||
@@ -175,110 +175,26 @@ func handle(
|
||||
protocol.TuneTCPBuffer(conn, tcpBuffer)
|
||||
|
||||
for {
|
||||
_ = conn.SetDeadline(time.Now().Add(20 * time.Second))
|
||||
|
||||
requestID, _, payload, err := protocol.ReadRequestFrame(conn)
|
||||
_ = conn.SetDeadline(time.Now().Add(30 * time.Second))
|
||||
req, err := wire.ReadRequest(conn)
|
||||
if err != nil {
|
||||
if debug != nil && debug.enabled && err != io.EOF {
|
||||
debug.errorf("peer=%v read request: %v", conn.RemoteAddr(), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if isChunkCommand(payload) {
|
||||
if err := processChunkCommand(
|
||||
conn,
|
||||
requestID,
|
||||
payload,
|
||||
token,
|
||||
allowPrivate,
|
||||
cache,
|
||||
tcpBuffer,
|
||||
manager,
|
||||
chunkMax,
|
||||
chunkBuffered,
|
||||
chunkPollWait,
|
||||
debug,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.Fields(string(payload))
|
||||
transport := "xor"
|
||||
|
||||
if len(parts) == 4 && parts[0] == "TUNNEL" {
|
||||
transport = "xor"
|
||||
} else if len(parts) == 5 && parts[0] == "TUNNEL2" {
|
||||
transport = strings.ToLower(parts[4])
|
||||
if transport != "raw" && transport != "xor" {
|
||||
_ = protocol.WriteResponseFrame(conn, requestID, []byte("ERR transport must be RAW or XOR"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
_ = protocol.WriteResponseFrame(
|
||||
conn,
|
||||
requestID,
|
||||
[]byte("ERR expected TUNNEL, TUNNEL2, or chunk command"),
|
||||
)
|
||||
if err := processWireRequest(
|
||||
conn,
|
||||
req,
|
||||
token,
|
||||
allowPrivate,
|
||||
cache,
|
||||
tcpBuffer,
|
||||
manager,
|
||||
chunkMax,
|
||||
bufferBytes,
|
||||
chunkPollWait,
|
||||
debug,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !tokenEqual(parts[1], token) {
|
||||
_ = protocol.WriteResponseFrame(
|
||||
conn,
|
||||
requestID,
|
||||
[]byte("ERR authentication failed"),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(parts[3])
|
||||
if err != nil || port < 1 || port > 65535 {
|
||||
_ = protocol.WriteResponseFrame(
|
||||
conn,
|
||||
requestID,
|
||||
[]byte("ERR invalid port"),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if debug != nil && debug.enabled {
|
||||
debug.logf("TUNNEL peer=%v target=%s:%d transport=%s", conn.RemoteAddr(), parts[2], port, transport)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
target, err := dialTarget(ctx, parts[2], port, allowPrivate, cache, tcpBuffer)
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
if debug != nil && debug.enabled {
|
||||
debug.errorf("TUNNEL target=%s:%d connect failed: %v", parts[2], port, err)
|
||||
}
|
||||
_ = protocol.WriteResponseFrame(
|
||||
conn,
|
||||
requestID,
|
||||
[]byte("ERR "+err.Error()),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer target.Close()
|
||||
|
||||
if err := protocol.WriteResponseFrame(conn, requestID, []byte("CONNECTED")); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_ = conn.SetDeadline(time.Time{})
|
||||
if transport == "raw" {
|
||||
protocol.RelayRaw(conn, target)
|
||||
} else {
|
||||
protocol.RelayXOR(conn, target)
|
||||
}
|
||||
if debug != nil && debug.enabled {
|
||||
debug.logf("TUNNEL closed peer=%v target=%s:%d transport=%s", conn.RemoteAddr(), parts[2], port, transport)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +209,7 @@ func main() {
|
||||
dnsCacheSize = flag.Int("dns-cache-size", 4096, "maximum cached DNS hostnames")
|
||||
tcpBuffer = flag.Int("tcp-buffer", 0, "optional TCP read/write buffer bytes; 0 keeps OS autotuning")
|
||||
chunkMax = flag.Int("chunk-max", 1048576, "maximum adaptive chunk payload bytes (32 bytes to 1 MiB)")
|
||||
chunkBuffered = flag.Int("chunk-buffered", 256, "maximum buffered destination chunks per session")
|
||||
chunkBuffered = flag.Int("chunk-buffered", 256, "compatibility buffer units; 256 = about 16 MiB per active session")
|
||||
chunkPollWait = flag.Duration("chunk-poll-wait", 200*time.Millisecond, "server long-poll wait for chunk data")
|
||||
sessionTimeout = flag.Duration("chunk-session-timeout", 2*time.Minute, "idle chunk session timeout")
|
||||
debugEnabled = flag.Bool("debug", false, "log session/connect/errors and periodic statistics")
|
||||
@@ -325,8 +241,15 @@ func main() {
|
||||
slots := make(chan struct{}, *maxConnections)
|
||||
cache := newDNSCache(*dnsCacheTTL, *dnsCacheSize)
|
||||
debug := newServerDebug(*debugEnabled, *debugChunks, *debugStats)
|
||||
manager := newChunkManager(*sessionTimeout, debug)
|
||||
fmt.Printf("adaptive_chunk_max=%d buffered_chunks=%d poll_wait=%s\n", *chunkMax, *chunkBuffered, chunkPollWait.String())
|
||||
bufferBytes := *chunkBuffered * 65536
|
||||
if bufferBytes < 1024*1024 {
|
||||
bufferBytes = 1024 * 1024
|
||||
}
|
||||
if bufferBytes > 64*1024*1024 {
|
||||
bufferBytes = 64 * 1024 * 1024
|
||||
}
|
||||
manager := newStreamManager(*sessionTimeout, debug)
|
||||
fmt.Printf("binary_transport=true chunk_max=%d buffer_bytes=%d poll_wait=%s\n", *chunkMax, bufferBytes, chunkPollWait.String())
|
||||
if debug.enabled {
|
||||
fmt.Printf("debug=true debug_chunks=%t stats_interval=%s\n", debug.chunks, debug.statsEvery)
|
||||
}
|
||||
@@ -353,7 +276,7 @@ func main() {
|
||||
slots,
|
||||
manager,
|
||||
*chunkMax,
|
||||
*chunkBuffered,
|
||||
bufferBytes,
|
||||
*chunkPollWait,
|
||||
debug,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user