2025-04-28 15:37:35 +00:00
# SmartProxy Project Hints
## Project Overview
- Package: `@push.rocks/smartproxy` – high-performance proxy supporting HTTP(S), TCP, WebSocket, and ACME integration.
- Written in TypeScript, compiled output in `dist_ts/` , uses ESM with NodeNext resolution.
2025-05-18 18:29:59 +00:00
## Important: ACME Configuration in v19.0.0
- **Breaking Change**: ACME configuration must be placed within individual route TLS settings, not at the top level
- Route-level ACME config is the ONLY way to enable SmartAcme initialization
- SmartCertManager requires email in route config for certificate acquisition
- Top-level ACME configuration is ignored in v19.0.0
2025-04-28 15:37:35 +00:00
## Repository Structure
- `ts/` – TypeScript source files:
- `index.ts` exports main modules.
- `plugins.ts` centralizes native and third-party imports.
- Subdirectories: `networkproxy/` , `nftablesproxy/` , `port80handler/` , `redirect/` , `smartproxy/` .
- Key classes: `ProxyRouter` (`classes.router.ts` ), `SmartProxy` (`classes.smartproxy.ts` ), plus handlers/managers.
- `dist_ts/` – transpiled `.js` and `.d.ts` files mirroring `ts/` structure.
- `test/` – test suites in TypeScript:
- `test.router.ts` – routing logic (hostname matching, wildcards, path parameters, config management).
- `test.smartproxy.ts` – proxy behavior tests (TCP forwarding, SNI handling, concurrency, chaining, timeouts).
- `test/helpers/` – utilities (e.g., certificates).
- `assets/certs/` – placeholder certificates for ACME and TLS.
## Development Setup
- Requires `pnpm` (v10+).
- Install dependencies: `pnpm install` .
- Build: `pnpm build` (runs `tsbuild --web --allowimplicitany` ).
- Test: `pnpm test` (runs `tstest test/` ).
- Format: `pnpm format` (runs `gitzone format` ).
## Testing Framework
- Uses `@push.rocks/tapbundle` (`tap` , `expect` , `expactAsync` ).
- Test files: must start with `test.` and use `.ts` extension.
- Run specific tests via `tsx` , e.g., `tsx test/test.router.ts` .
## Coding Conventions
- Import modules via `plugins.ts` :
```ts
import * as plugins from './plugins.ts';
const server = new plugins.http.Server();
```
- Reference plugins with full path: `plugins.acme` , `plugins.smartdelay` , `plugins.minimatch` , etc.
- Path patterns support globs (`*` ) and parameters (`:param` ) in `ProxyRouter` .
- Wildcard hostname matching leverages `minimatch` patterns.
## Key Components
- **ProxyRouter**
- Methods: `routeReq` , `routeReqWithDetails` .
- Hostname matching: case-insensitive, strips port, supports exact, wildcard, TLD, complex patterns.
- Path routing: exact, wildcard, parameter extraction (`pathParams` ), returns `pathMatch` and `pathRemainder` .
- Config API: `setNewProxyConfigs` , `addProxyConfig` , `removeProxyConfig` , `getHostnames` , `getProxyConfigs` .
- **SmartProxy**
- Manages one or more `net.Server` instances to forward TCP streams.
- Options: `preserveSourceIP` , `defaultAllowedIPs` , `globalPortRanges` , `sniEnabled` .
- DomainConfigManager: round-robin selection for multiple target IPs.
- Graceful shutdown in `stop()` , ensures no lingering servers or sockets.
## Notable Points
- **TSConfig**: `module: NodeNext` , `verbatimModuleSyntax` , allows `.js` extension imports in TS.
- Mermaid diagrams and architecture flows in `readme.md` illustrate component interactions and protocol flows.
- CLI entrypoint (`cli.js` ) supports command-line usage (ACME, proxy controls).
- ACME and certificate handling via `Port80Handler` and `helpers.certificates.ts` .
2025-05-18 18:29:59 +00:00
## ACME/Certificate Configuration Example (v19.0.0)
```typescript
const proxy = new SmartProxy({
routes: [{
name: 'example.com',
match: { domains: 'example.com', ports: 443 },
action: {
type: 'forward',
target: { host: 'localhost', port: 8080 },
tls: {
mode: 'terminate',
certificate: 'auto',
acme: { // ACME config MUST be here, not at top level
email: 'ssl@example .com',
useProduction: false,
challengePort: 80
}
}
}
}]
});
```
2025-04-28 15:37:35 +00:00
## TODOs / Considerations
- Ensure import extensions in source match build outputs (`.ts` vs `.js` ).
- Update `plugins.ts` when adding new dependencies.
- Maintain test coverage for new routing or proxy features.
2025-05-18 18:29:59 +00:00
- Keep `ts/` and `dist_ts/` in sync after refactors.
2025-05-19 19:59:22 +00:00
- Consider implementing top-level ACME config support for backward compatibility
## HTTP-01 ACME Challenge Fix (v19.3.8)
### Issue
Non-TLS connections on ports configured in `useHttpProxy` were not being forwarded to HttpProxy. This caused ACME HTTP-01 challenges to fail when the ACME port (usually 80) was included in `useHttpProxy` .
### Root Cause
In the `RouteConnectionHandler.handleForwardAction` method, only connections with TLS settings (mode: 'terminate' or 'terminate-and-reencrypt') were being forwarded to HttpProxy. Non-TLS connections were always handled as direct connections, even when the port was configured for HttpProxy.
### Solution
Added a check for non-TLS connections on ports listed in `useHttpProxy` :
```typescript
// 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
this.httpProxyBridge.forwardToHttpProxy(/*...*/);
return;
}
```
### Test Coverage
- `test/test.http-fix-unit.ts` - Unit tests verifying the fix
- Tests confirm that non-TLS connections on HttpProxy ports are properly forwarded
- Tests verify that non-HttpProxy ports still use direct connections
### Configuration Example
```typescript
const proxy = new SmartProxy({
useHttpProxy: [80], // Enable HttpProxy for port 80
httpProxyPort: 8443,
acme: {
email: 'ssl@example .com',
port: 80
},
routes: [
// Your routes here
]
});
2025-05-19 22:07:08 +00:00
```
## ACME Certificate Provisioning Timing Fix (v19.3.9)
### Issue
Certificate provisioning would start before ports were listening, causing ACME HTTP-01 challenges to fail with connection refused errors.
### Root Cause
SmartProxy initialization sequence:
1. Certificate manager initialized → immediately starts provisioning
2. Ports start listening (too late for ACME challenges)
### Solution
Deferred certificate provisioning until after ports are ready:
```typescript
// SmartCertManager.initialize() now skips automatic provisioning
// SmartProxy.start() calls provisionAllCertificates() directly after ports are listening
```
### Test Coverage
- `test/test.acme-timing-simple.ts` - Verifies proper timing sequence
### Migration
Update to v19.3.9+, no configuration changes needed.