Mult Port + TCP Calibration (SSH DEAD)
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"dragontcp/internal/cover"
|
||||
"dragontcp/internal/protocol"
|
||||
)
|
||||
|
||||
@@ -135,6 +136,17 @@ func addressAllowed(addr netip.Addr, allowPrivate bool) bool {
|
||||
}
|
||||
|
||||
func dialTarget(ctx context.Context, host string, port int, allowPrivate bool, cache *dnsCache, tcpBuffer int) (net.Conn, error) {
|
||||
if internalAddr, ok := lookupInternalTarget(host, port); ok {
|
||||
d := net.Dialer{Timeout: 10 * time.Second, KeepAlive: 30 * time.Second}
|
||||
conn, err := d.DialContext(ctx, "tcp", internalAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
protocol.TuneTCP(conn)
|
||||
protocol.TuneTCPBuffer(conn, tcpBuffer)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
ips, err := cache.resolve(ctx, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -215,11 +227,24 @@ func handle(
|
||||
return
|
||||
}
|
||||
clearPayload := false
|
||||
coverID := uint16(0)
|
||||
covered := false
|
||||
if profiled, ok := conn.(interface{ ClearPayload() bool }); ok {
|
||||
clearPayload = profiled.ClearPayload()
|
||||
}
|
||||
if profiled, ok := conn.(interface{ CoverProfile() cover.Profile }); ok {
|
||||
profile := profiled.CoverProfile()
|
||||
if profile.Enabled {
|
||||
covered = true
|
||||
coverID = profile.ID
|
||||
}
|
||||
}
|
||||
if debug != nil && debug.enabled {
|
||||
debug.logf("WIRE peer=%v mode=binary header_mask=%02x clear_payload=%t", conn.RemoteAddr(), headerMask, clearPayload)
|
||||
if covered {
|
||||
debug.logf("WIRE peer=%v mode=binary header_mask=%02x clear_payload=%t cover_id=%04x", conn.RemoteAddr(), headerMask, clearPayload, coverID)
|
||||
} else {
|
||||
debug.logf("WIRE peer=%v mode=binary header_mask=%02x clear_payload=%t cover_id=direct", conn.RemoteAddr(), headerMask, clearPayload)
|
||||
}
|
||||
}
|
||||
|
||||
handleBinary(conn, headerMask, clearPayload, token, allowPrivate, cache, tcpBuffer, manager,
|
||||
@@ -268,6 +293,7 @@ func acceptLoop(
|
||||
}
|
||||
|
||||
func main() {
|
||||
sshCLI := registerSSHCLIFlags()
|
||||
var (
|
||||
host = flag.String("host", "0.0.0.0", "listen host")
|
||||
port = flag.Int("port", 53, "listen port")
|
||||
@@ -285,9 +311,27 @@ func main() {
|
||||
debugEnabled = flag.Bool("debug", false, "log session/connect/errors and periodic statistics")
|
||||
debugChunks = flag.Bool("debug-chunks", false, "log every chunk protocol record; very verbose")
|
||||
debugStats = flag.Duration("debug-stats-interval", 5*time.Second, "periodic debug statistics interval; 0 disables")
|
||||
|
||||
sshEnable = flag.Bool("ssh-enable", true, "enable the internal tunnel-only SSH service")
|
||||
sshListen = flag.String("ssh-listen", defaultSSHListen, "internal fake SSH listen address")
|
||||
sshInternalHost = flag.String("ssh-internal-host", defaultSSHInternalHost, "reserved DragonTCP target name used by clients for SSH")
|
||||
sshHostKey = flag.String("ssh-host-key", "dragontcp_ssh_host_key", "SSH host private-key path; generated automatically if missing")
|
||||
udpgwEnable = flag.Bool("udpgw-enable", true, "enable integrated BadVPN-compatible UDPGW")
|
||||
udpgwListen = flag.String("udpgw-listen", "127.0.0.1:7400", "UDPGW listen address; loopback is recommended")
|
||||
udpgwInternalHost = flag.String("udpgw-internal-host", "dragontcp-udpgw.internal", "reserved SSH direct-tcpip target name for UDPGW")
|
||||
udpgwMaxClients = flag.Int("udpgw-max-clients", 10000, "maximum concurrent UDPGW TCP clients")
|
||||
udpgwDebug = flag.Bool("udpgw-debug", false, "verbose UDPGW errors")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if handled, err := handleSSHCLI(sshCLI); handled {
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if *chunkMax < 32 || *chunkMax > protocol.MaxChunkPayload {
|
||||
fmt.Fprintf(os.Stderr, "--chunk-max must be between 32 and %d\n", protocol.MaxChunkPayload)
|
||||
os.Exit(2)
|
||||
@@ -297,6 +341,58 @@ func main() {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
cache := newDNSCache(*dnsCacheTTL, *dnsCacheSize)
|
||||
|
||||
var udpServer *udpgwServer
|
||||
if *udpgwEnable {
|
||||
var err error
|
||||
udpServer, err = startUDPGWServer(udpgwServerConfig{
|
||||
Listen: *udpgwListen, MaxClients: *udpgwMaxClients, Debug: *udpgwDebug,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "UDPGW start failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer udpServer.Close()
|
||||
_, udpPortText, err := net.SplitHostPort(udpServer.ln.Addr().String())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid UDPGW listener: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
udpPort, err := strconv.Atoi(udpPortText)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid UDPGW port: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
registerSSHOnlyInternalTarget(*udpgwInternalHost, udpPort, udpServer.ln.Addr().String())
|
||||
fmt.Printf("udpgw=true listen=%s internal_target=%s:%d max_clients=%d\n", udpServer.ln.Addr(), *udpgwInternalHost, udpPort, *udpgwMaxClients)
|
||||
}
|
||||
|
||||
var sshListener net.Listener
|
||||
if *sshEnable {
|
||||
sshStore := newSSHUserStore(*sshCLI.usersPath)
|
||||
listener, fingerprint, err := startFakeSSH(*sshListen, *sshHostKey, sshStore, *allowPrivate, cache, *tcpBuffer)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "fake SSH start failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
sshListener = listener
|
||||
defer sshListener.Close()
|
||||
sshBoundAddr := sshListener.Addr().String()
|
||||
_, sshPortText, err := net.SplitHostPort(sshBoundAddr)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid fake SSH listener: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
sshPort, err := strconv.Atoi(sshPortText)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid fake SSH listener port: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
registerInternalTarget(*sshInternalHost, sshPort, sshBoundAddr)
|
||||
fmt.Printf("fake_ssh=true listen=%s internal_target=%s:%d hostkey=%s users=%s\n", sshBoundAddr, *sshInternalHost, sshPort, fingerprint, *sshCLI.usersPath)
|
||||
}
|
||||
|
||||
listenAddr := net.JoinHostPort(*host, strconv.Itoa(*port))
|
||||
ln, err := net.Listen("tcp", listenAddr)
|
||||
if err != nil {
|
||||
@@ -324,7 +420,6 @@ func main() {
|
||||
fmt.Printf("max_connections=%d tcp_buffer=%d\n", *maxConnections, *tcpBuffer)
|
||||
|
||||
slots := make(chan struct{}, *maxConnections)
|
||||
cache := newDNSCache(*dnsCacheTTL, *dnsCacheSize)
|
||||
debug := newServerDebug(*debugEnabled, *debugChunks, *debugStats)
|
||||
bufferBytes := *chunkBuffered * 65536
|
||||
if bufferBytes < 1024*1024 {
|
||||
|
||||
Reference in New Issue
Block a user