smartproxy/docs/http-01-acme-fix.md

3.6 KiB

HTTP-01 ACME Challenge Fix (v19.3.8)

Problem Description

In SmartProxy v19.3.7 and earlier, ACME HTTP-01 challenges would fail when port 80 was configured to use HttpProxy via the useHttpProxy configuration option. The issue was that non-TLS connections on ports listed in useHttpProxy were not being forwarded to HttpProxy, instead being handled as direct connections.

Root Cause

The bug was located in the RouteConnectionHandler.handleForwardAction method in ts/proxies/smart-proxy/route-connection-handler.ts. The method only forwarded connections to HttpProxy if they had TLS settings with mode 'terminate' or 'terminate-and-reencrypt'. Non-TLS connections (like HTTP on port 80) were always handled as direct connections, regardless of the useHttpProxy configuration.

Solution

The fix adds a check for non-TLS connections on ports listed in the useHttpProxy array:

// No TLS settings - check if this port should use HttpProxy
const isHttpProxyPort = this.settings.useHttpProxy?.includes(record.localPort);

if (isHttpProxyPort && this.httpProxyBridge.getHttpProxy()) {
  // Forward non-TLS connections to HttpProxy if configured
  if (this.settings.enableDetailedLogging) {
    console.log(
      `[${connectionId}] Using HttpProxy for non-TLS connection on port ${record.localPort}`
    );
  }
  
  this.httpProxyBridge.forwardToHttpProxy(
    connectionId,
    socket,
    record,
    initialChunk,
    this.settings.httpProxyPort || 8443,
    (reason) => this.connectionManager.initiateCleanupOnce(record, reason)
  );
  return;
}

Configuration

To enable ACME HTTP-01 challenges on port 80 with HttpProxy:

const proxy = new SmartProxy({
  useHttpProxy: [80], // Must include port 80 for HTTP-01 challenges
  httpProxyPort: 8443, // Default HttpProxy port
  acme: {
    email: 'ssl@example.com',
    port: 80, // ACME challenge port
    useProduction: false
  },
  routes: [
    {
      name: 'https-route',
      match: {
        ports: 443,
        domains: 'example.com'
      },
      action: {
        type: 'forward',
        target: { host: 'localhost', port: 8080 },
        tls: {
          mode: 'terminate',
          certificate: 'auto',
          acme: {
            email: 'ssl@example.com',
            useProduction: false
          }
        }
      }
    }
  ]
});

Testing

The fix is verified by unit tests in test/test.http-fix-unit.ts:

  1. Test 1: Verifies that non-TLS connections on ports in useHttpProxy are forwarded to HttpProxy
  2. Test 2: Confirms that ports not in useHttpProxy still use direct connections
  3. Test 3: Validates that ACME HTTP-01 challenges on port 80 work correctly with HttpProxy

Impact

This fix enables proper ACME HTTP-01 challenge handling when:

  1. Port 80 is configured in the useHttpProxy array
  2. An ACME challenge route is configured to use HTTP-01 validation
  3. Certificate provisioning with certificate: 'auto' is used

Without this fix, HTTP-01 challenges would fail because the challenge requests would not reach the ACME handler in HttpProxy.

Migration Guide

If you were experiencing ACME HTTP-01 challenge failures:

  1. Update to SmartProxy v19.3.8 or later
  2. Ensure port 80 is included in your useHttpProxy configuration
  3. Verify your ACME configuration includes the correct email and port settings
  4. Test certificate renewal with staging ACME first (useProduction: false)
  • ACME HTTP-01 challenges timing out on port 80
  • HTTP requests not being parsed on configured HttpProxy ports
  • Certificate provisioning failing with "connection timeout" errors