feat(smart-proxy): Improve connection/rate-limit atomicity, SNI parsing, HttpProxy & ACME orchestration, and routing utilities
This commit is contained in:
168
readme.hints.md
168
readme.hints.md
@@ -345,4 +345,170 @@ new SmartProxy({
|
||||
1. Implement proper certificate expiry date extraction using X.509 parsing
|
||||
2. Add support for returning expiry date with custom certificates
|
||||
3. Consider adding validation for custom certificate format
|
||||
4. Add events/hooks for certificate provisioning lifecycle
|
||||
4. Add events/hooks for certificate provisioning lifecycle
|
||||
|
||||
## HTTPS/TLS Configuration Guide
|
||||
|
||||
SmartProxy supports three TLS modes for handling HTTPS traffic. Understanding when to use each mode is crucial for correct configuration.
|
||||
|
||||
### TLS Mode: Passthrough (SNI Routing)
|
||||
|
||||
**When to use**: Backend server handles its own TLS certificates.
|
||||
|
||||
**How it works**:
|
||||
1. Client connects with TLS ClientHello containing SNI (Server Name Indication)
|
||||
2. SmartProxy extracts the SNI hostname without decrypting
|
||||
3. Connection is forwarded to backend as-is (still encrypted)
|
||||
4. Backend server terminates TLS with its own certificate
|
||||
|
||||
**Configuration**:
|
||||
```typescript
|
||||
{
|
||||
match: { ports: 443, domains: 'backend.example.com' },
|
||||
action: {
|
||||
type: 'forward',
|
||||
targets: [{ host: 'backend-server', port: 443 }],
|
||||
tls: { mode: 'passthrough' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**:
|
||||
- Backend must have valid TLS certificate for the domain
|
||||
- Client's SNI must be present (session tickets without SNI will be rejected)
|
||||
- No HTTP-level inspection possible (encrypted end-to-end)
|
||||
|
||||
### TLS Mode: Terminate
|
||||
|
||||
**When to use**: SmartProxy handles TLS, backend receives plain HTTP.
|
||||
|
||||
**How it works**:
|
||||
1. Client connects with TLS ClientHello
|
||||
2. SmartProxy terminates TLS (decrypts traffic)
|
||||
3. Decrypted HTTP is forwarded to backend on plain HTTP port
|
||||
4. Backend receives unencrypted traffic
|
||||
|
||||
**Configuration**:
|
||||
```typescript
|
||||
{
|
||||
match: { ports: 443, domains: 'api.example.com' },
|
||||
action: {
|
||||
type: 'forward',
|
||||
targets: [{ host: 'localhost', port: 8080 }], // HTTP backend
|
||||
tls: {
|
||||
mode: 'terminate',
|
||||
certificate: 'auto' // Let's Encrypt, or provide { key, cert }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**:
|
||||
- ACME email configured for auto certificates: `acme: { email: 'admin@example.com' }`
|
||||
- Port 80 available for HTTP-01 challenges (or use DNS-01)
|
||||
- Backend accessible on HTTP port
|
||||
|
||||
### TLS Mode: Terminate and Re-encrypt
|
||||
|
||||
**When to use**: SmartProxy handles client TLS, but backend also requires TLS.
|
||||
|
||||
**How it works**:
|
||||
1. Client connects with TLS ClientHello
|
||||
2. SmartProxy terminates client TLS (decrypts)
|
||||
3. SmartProxy creates new TLS connection to backend
|
||||
4. Traffic is re-encrypted for the backend connection
|
||||
|
||||
**Configuration**:
|
||||
```typescript
|
||||
{
|
||||
match: { ports: 443, domains: 'secure.example.com' },
|
||||
action: {
|
||||
type: 'forward',
|
||||
targets: [{ host: 'backend-tls', port: 443 }], // HTTPS backend
|
||||
tls: {
|
||||
mode: 'terminate-and-reencrypt',
|
||||
certificate: 'auto'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**:
|
||||
- Same as 'terminate' mode
|
||||
- Backend must have valid TLS (can be self-signed for internal use)
|
||||
|
||||
### HttpProxy Integration
|
||||
|
||||
For TLS termination modes (`terminate` and `terminate-and-reencrypt`), SmartProxy uses an internal HttpProxy component:
|
||||
|
||||
- HttpProxy listens on an internal port (default: 8443)
|
||||
- SmartProxy forwards TLS connections to HttpProxy for termination
|
||||
- Client IP is preserved via `CLIENT_IP:` header protocol
|
||||
- HTTP/2 and WebSocket are supported after TLS termination
|
||||
|
||||
**Configuration**:
|
||||
```typescript
|
||||
{
|
||||
useHttpProxy: [443], // Ports that use HttpProxy for TLS termination
|
||||
httpProxyPort: 8443, // Internal HttpProxy port
|
||||
acme: {
|
||||
email: 'admin@example.com',
|
||||
useProduction: true // false for Let's Encrypt staging
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Common Configuration Patterns
|
||||
|
||||
**HTTP to HTTPS Redirect**:
|
||||
```typescript
|
||||
import { createHttpToHttpsRedirect } from '@push.rocks/smartproxy';
|
||||
|
||||
const redirectRoute = createHttpToHttpsRedirect(['example.com', 'www.example.com']);
|
||||
```
|
||||
|
||||
**Complete HTTPS Server (with redirect)**:
|
||||
```typescript
|
||||
import { createCompleteHttpsServer } from '@push.rocks/smartproxy';
|
||||
|
||||
const routes = createCompleteHttpsServer(
|
||||
'example.com',
|
||||
{ host: 'localhost', port: 8080 },
|
||||
{ certificate: 'auto' }
|
||||
);
|
||||
```
|
||||
|
||||
**Load Balancer with Health Checks**:
|
||||
```typescript
|
||||
import { createLoadBalancerRoute } from '@push.rocks/smartproxy';
|
||||
|
||||
const lbRoute = createLoadBalancerRoute(
|
||||
'api.example.com',
|
||||
[
|
||||
{ host: 'backend1', port: 8080 },
|
||||
{ host: 'backend2', port: 8080 },
|
||||
{ host: 'backend3', port: 8080 }
|
||||
],
|
||||
{ tls: { mode: 'terminate', certificate: 'auto' } }
|
||||
);
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**"No SNI detected" errors**:
|
||||
- Client is using TLS session resumption without SNI
|
||||
- Solution: Configure route for TLS termination (allows session resumption)
|
||||
|
||||
**"HttpProxy not available" errors**:
|
||||
- `useHttpProxy` not configured for the port
|
||||
- Solution: Add port to `useHttpProxy` array in settings
|
||||
|
||||
**Certificate provisioning failures**:
|
||||
- Port 80 not accessible for HTTP-01 challenges
|
||||
- ACME email not configured
|
||||
- Solution: Ensure port 80 is available and `acme.email` is set
|
||||
|
||||
**Connection timeouts to HttpProxy**:
|
||||
- CLIENT_IP header parsing timeout (default: 2000ms)
|
||||
- Network congestion between SmartProxy and HttpProxy
|
||||
- Solution: Check localhost connectivity, increase timeout if needed
|
||||
Reference in New Issue
Block a user