dcrouter/readme.plan.md
Philipp Kunz b11fea7334 feat(socket-handler): implement direct socket passing for DNS and email services
- Add socket-handler mode eliminating internal port binding for improved performance
- Add `dnsDomain` config option for automatic DNS-over-HTTPS (DoH) setup
- Add `useSocketHandler` flag to email config for direct socket processing
- Update SmartProxy route generation to support socket-handler actions
- Integrate smartdns with manual HTTPS mode for DoH without port binding
- Add automatic route creation for DNS paths when dnsDomain is configured
- Update documentation with socket-handler configuration and benefits
- Improve resource efficiency by eliminating internal port forwarding
2025-05-29 16:26:19 +00:00

9.4 KiB

DcRouter Socket-Handler Integration Plan

First line: Remember to reread CLAUDE.md file for guidelines.

Overview

Integrate socket-handler support for both DNS and Mail services in DcRouter, allowing smartproxy to pass sockets directly instead of servers listening on ports.

Core Logic

  • DNS: If dnsDomain is set, DnsServer is instantiated with socket-handler for HTTPS/DoH
  • Mail: If useSocketHandler is enabled in emailConfig, mail servers accept sockets from smartproxy
  • Automatic Routing: Setting these options automatically configures smartproxy routes

Architecture

DNS Architecture

  • HTTPS/DoH Traffic: smartproxy → socket-handler → smartdns (no port listening)
  • UDP Traffic: Direct to smartdns DnsServer on VM IP:53 (bypasses smartproxy)
  • Automatic Setup: Setting dnsDomain triggers all DNS infrastructure

Mail Architecture

  • Socket-Handler Mode: smartproxy → socket-handler → mail server (no port listening)
  • Traditional Mode: smartproxy → forward → mail server (listening on ports)
  • Configurable: useSocketHandler flag determines the mode

Implementation Steps

1. Analyze Current Architecture

  • Examine how DcRouter currently integrates services
  • Study email server socket handling in SmtpServer
  • Check existing smartproxy socket-handler patterns
  • Review UnifiedEmailServer connection handling

2. DNS Socket-Handler Implementation

2.1 Create DNS Socket Handler

  • Create a custom socket handler that processes DNS-over-HTTPS requests
  • Handler should use smartdns without port binding
  • Use built-in handleHttpsSocket method from smartdns
  • Set manualHttpsMode: true in DnsServer options

2.2 Configure smartdns DnsServer

  • Create DnsServer instance with UDP only on VM IP interface
  • Set manualHttpsMode: true to disable HTTPS port binding
  • Configure to listen on port 53 for UDP traffic only
  • Use handleHttpsSocket method for DoH sockets

3. Mail Socket-Handler Implementation

3.1 Modify SmtpServer

  • ConnectionManager already has handleConnection method
  • Connection handling already works with provided sockets
  • Session management works with socket-handler mode
  • Backward compatibility maintained

3.2 Update UnifiedEmailServer

  • Add useSocketHandler flag to IUnifiedEmailServerOptions
  • Modify start() to skip server creation when useSocketHandler is true
  • Add handleSocket method to accept sockets from smartproxy
  • All email processing works in socket-handler mode

3.3 Create Mail Socket Handler

  • Create socket handler for SMTP/submission/SMTPS
  • Handle TLS for port 465 (immediate TLS wrapping)
  • Pass sockets to UnifiedEmailServer.handleSocket

4. DcRouter Integration

4.1 Configuration Updates

  • Add dnsDomain property to DcRouter config
  • Add useSocketHandler to email config options
  • Update interface definitions

4.2 Route Generation Updates

  • Modify generateEmailRoutes to create socket-handler actions when enabled
  • Create DNS routes with socket-handler actions
  • Ensure proper domain and path matching

4.3 Service Lifecycle

  • Update setupSmartProxy to handle socket-handler routes
  • Services start correctly without port binding
  • Socket cleanup handled by connection managers

5. SmartProxy Route Configuration

  • DNS routes: match dnsDomain with paths /dns-query and /resolve
  • Mail routes: match ports 25, 587, 465 with socket-handler actions
  • Configure TLS handling for each protocol appropriately
  • Automatic Let's Encrypt via smartproxy certificate: 'auto'

6. Testing (To be done)

6.1 DNS Testing

  • Test that DNS server is NOT instantiated when dnsDomain is not set
  • Test that DNS server IS instantiated when dnsDomain is set
  • Test UDP DNS queries on port 53
  • Test DoH queries through smartproxy socket-handler
  • Verify HTTP/2 support for DoH

6.2 Mail Testing

  • Test traditional port-based mail delivery
  • Test socket-handler mail delivery
  • Verify STARTTLS works in socket-handler mode
  • Test SMTPS (port 465) with socket-handler
  • Ensure connection pooling works correctly

6.3 Integration Testing

  • Test both DNS and Mail with socket-handlers simultaneously
  • Verify no port conflicts
  • Test automatic startup/shutdown
  • Load test socket-handler performance

Technical Details

DcRouter Configuration

// DcRouter config with socket-handler support
const dcRouterConfig = {
  // ... other config
  dnsDomain: 'example.com', // Optional - if set, DNS server is enabled
  emailConfig: {
    ports: [25, 587, 465],
    domains: ['mail.example.com'],
    useSocketHandler: true, // Enable socket-handler mode for mail
    routes: [/* email routing rules */]
  }
}

DNS Implementation

Conditional DNS Instantiation

// In DcRouter startup logic
if (config.dnsDomain) {
  // Create DNS server instance
  this.dnsServer = new DnsServer({
    udpPort: 53,
    udpBindAddress: vmIpAddress,
    httpsPort: undefined, // No HTTPS listening
    dnssecZone: config.dnsDomain
  });
  
  // Create smartproxy route for DoH
  const dnsRoute = {
    match: {
      domain: config.dnsDomain,
      path: ['/dns-query', '/resolve']
    },
    action: {
      type: 'socket-handler',
      handler: this.createDnsSocketHandler()
    }
  };
}

DNS Socket Handler

const createDnsSocketHandler = () => {
  return async (socket: net.Socket) => {
    // Handle HTTP/2 for DoH
    const session = http2.createSession(socket);
    
    session.on('stream', async (stream, headers) => {
      if (headers[':path'] === '/dns-query') {
        const dnsQuery = await parseDnsQuery(stream);
        const response = await dnsServer.resolveQuery(dnsQuery);
        stream.respond({ ':status': 200, 'content-type': 'application/dns-message' });
        stream.end(response);
      }
    });
  };
}

Mail Implementation

Email Route Generation with Socket-Handler

private generateEmailRoutes(emailConfig: IUnifiedEmailServerOptions): IRouteConfig[] {
  const routes: IRouteConfig[] = [];
  
  for (const port of emailConfig.ports) {
    const action = emailConfig.useSocketHandler
      ? {
          type: 'socket-handler',
          handler: this.createMailSocketHandler(port)
        }
      : {
          type: 'forward',
          target: { host: 'localhost', port: mapPort(port) }
        };
    
    routes.push({
      match: { ports: [port] },
      action
    });
  }
  
  return routes;
}

Mail Socket Handler

const createMailSocketHandler = (port: number) => {
  return async (socket: net.Socket) => {
    // Determine protocol based on port
    const isSecure = port === 465;
    
    if (isSecure) {
      // For SMTPS, handle TLS immediately
      const tlsSocket = new tls.TLSSocket(socket, {
        isServer: true,
        cert: tlsCert,
        key: tlsKey
      });
      await this.emailServer.handleSocket(tlsSocket, port);
    } else {
      // For SMTP/Submission, pass raw socket
      await this.emailServer.handleSocket(socket, port);
    }
  };
}

UnifiedEmailServer Socket Handling

// In UnifiedEmailServer class
public async handleSocket(socket: net.Socket, port: number): Promise<void> {
  // Create session for this socket
  const session = this.sessionManager.createSession(socket);
  
  // Handle connection based on port
  switch (port) {
    case 25:  // SMTP
    case 587: // Submission (STARTTLS)
      await this.connectionManager.handleConnection(socket, session);
      break;
    case 465: // SMTPS (already TLS)
      await this.connectionManager.handleSecureConnection(socket, session);
      break;
  }
}

## Dependencies
- @push.rocks/smartproxy (already integrated)
- @push.rocks/smartdns (to be added)

## Implementation Phases

### Phase 1: DNS Socket-Handler (Priority)
1. Add smartdns dependency
2. Implement DNS socket-handler
3. Add dnsDomain configuration
4. Test DoH functionality

### Phase 2: Mail Socket-Handler  
1. Refactor SmtpServer for socket handling
2. Update UnifiedEmailServer
3. Implement mail socket-handlers
4. Add useSocketHandler configuration
5. Test all mail protocols

### Phase 3: Integration & Testing
1. Full integration testing
2. Performance benchmarking
3. Documentation updates
4. Migration guide for existing users

## Notes

### DNS Notes
- UDP traffic bypasses proxy entirely (kernel-level routing)
- DoH provides encrypted DNS over HTTPS through proxy
- Socket handler allows DNS processing without port binding
- DNS functionality is entirely optional - only enabled when dnsDomain is configured
- Setting dnsDomain triggers automatic setup of all DNS infrastructure
- Automatic Let's Encrypt certificate provisioning for configured dnsDomain

### Mail Notes
- Socket-handler mode eliminates internal port binding for mail services
- Traditional port forwarding mode remains available for compatibility
- STARTTLS negotiation handled within socket-handler for ports 25/587
- Port 465 (SMTPS) requires immediate TLS handshake in socket-handler
- Connection pooling and session management work in both modes
- Socket-handler reduces latency by eliminating internal forwarding

### General Benefits
- Reduced resource usage (no internal port binding)
- Better performance (direct socket passing)
- Simplified configuration (automatic route creation)
- Enhanced security (no exposed internal ports)
- Unified approach for all services through smartproxy