@push.rocks/smartproxy 19.3.2 → 19.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/forwarding/factory/forwarding-factory.js +29 -1
- package/dist_ts/http/index.d.ts +1 -3
- package/dist_ts/http/index.js +4 -10
- package/dist_ts/http/models/http-types.d.ts +4 -91
- package/dist_ts/http/models/http-types.js +5 -60
- package/dist_ts/http/router/proxy-router.d.ts +1 -1
- package/dist_ts/http/router/route-router.d.ts +1 -1
- package/dist_ts/index.d.ts +9 -7
- package/dist_ts/index.js +10 -7
- package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.d.ts +2 -2
- package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.js +1 -1
- package/dist_ts/proxies/{network-proxy → http-proxy}/connection-pool.d.ts +2 -2
- package/dist_ts/proxies/http-proxy/connection-pool.js +210 -0
- package/dist_ts/proxies/http-proxy/context-creator.js +108 -0
- package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.js +1 -1
- package/dist_ts/proxies/http-proxy/handlers/index.d.ts +5 -0
- package/dist_ts/proxies/http-proxy/handlers/index.js +6 -0
- package/dist_ts/proxies/http-proxy/handlers/redirect-handler.d.ts +18 -0
- package/dist_ts/proxies/http-proxy/handlers/redirect-handler.js +78 -0
- package/dist_ts/proxies/http-proxy/handlers/static-handler.d.ts +19 -0
- package/dist_ts/proxies/http-proxy/handlers/static-handler.js +203 -0
- package/dist_ts/proxies/{network-proxy/network-proxy.d.ts → http-proxy/http-proxy.d.ts} +10 -9
- package/dist_ts/proxies/{network-proxy/network-proxy.js → http-proxy/http-proxy.js} +13 -12
- package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.js +1 -1
- package/dist_ts/proxies/http-proxy/http2-request-handler.js +201 -0
- package/dist_ts/proxies/{network-proxy → http-proxy}/index.d.ts +2 -2
- package/dist_ts/proxies/http-proxy/index.js +12 -0
- package/dist_ts/proxies/http-proxy/models/http-types.d.ts +119 -0
- package/dist_ts/proxies/http-proxy/models/http-types.js +112 -0
- package/dist_ts/proxies/http-proxy/models/index.d.ts +5 -0
- package/dist_ts/proxies/http-proxy/models/index.js +6 -0
- package/dist_ts/proxies/{network-proxy → http-proxy}/models/types.d.ts +2 -2
- package/dist_ts/proxies/http-proxy/models/types.js +276 -0
- package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.d.ts +3 -3
- package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.js +2 -2
- package/dist_ts/proxies/http-proxy/security-manager.js +255 -0
- package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.d.ts +3 -3
- package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.js +2 -2
- package/dist_ts/proxies/index.d.ts +5 -5
- package/dist_ts/proxies/index.js +5 -5
- package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +4 -4
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +11 -11
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +41 -0
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +121 -0
- package/dist_ts/proxies/smart-proxy/index.d.ts +2 -1
- package/dist_ts/proxies/smart-proxy/index.js +4 -2
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +2 -2
- package/dist_ts/proxies/smart-proxy/port-manager.js +3 -3
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +3 -3
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +24 -265
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +25 -25
- package/dist_ts/routing/index.d.ts +5 -0
- package/dist_ts/routing/index.js +8 -0
- package/dist_ts/routing/models/http-types.d.ts +6 -0
- package/dist_ts/routing/models/http-types.js +7 -0
- package/dist_ts/routing/router/index.d.ts +8 -0
- package/dist_ts/routing/router/index.js +7 -0
- package/dist_ts/{classes.router.d.ts → routing/router/proxy-router.d.ts} +14 -11
- package/dist_ts/{classes.router.js → routing/router/proxy-router.js} +2 -2
- package/dist_ts/routing/router/route-router.d.ts +108 -0
- package/dist_ts/routing/router/route-router.js +393 -0
- package/package.json +1 -1
- package/readme.md +12 -12
- package/readme.plan.md +152 -257
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/forwarding/factory/forwarding-factory.ts +28 -0
- package/ts/index.ts +13 -9
- package/ts/proxies/{network-proxy → http-proxy}/certificate-manager.ts +2 -2
- package/ts/proxies/{network-proxy → http-proxy}/connection-pool.ts +2 -2
- package/ts/proxies/http-proxy/handlers/index.ts +6 -0
- package/ts/proxies/http-proxy/handlers/redirect-handler.ts +105 -0
- package/ts/proxies/http-proxy/handlers/static-handler.ts +251 -0
- package/ts/proxies/{network-proxy/network-proxy.ts → http-proxy/http-proxy.ts} +15 -14
- package/ts/proxies/{network-proxy → http-proxy}/index.ts +3 -3
- package/ts/proxies/http-proxy/models/http-types.ts +165 -0
- package/ts/proxies/http-proxy/models/index.ts +5 -0
- package/ts/proxies/{network-proxy → http-proxy}/models/types.ts +2 -2
- package/ts/proxies/{network-proxy → http-proxy}/request-handler.ts +3 -3
- package/ts/proxies/{network-proxy → http-proxy}/websocket-handler.ts +3 -3
- package/ts/proxies/index.ts +7 -7
- package/ts/proxies/smart-proxy/certificate-manager.ts +10 -10
- package/ts/proxies/smart-proxy/{network-proxy-bridge.ts → http-proxy-bridge.ts} +44 -44
- package/ts/proxies/smart-proxy/index.ts +4 -1
- package/ts/proxies/smart-proxy/models/interfaces.ts +3 -3
- package/ts/proxies/smart-proxy/port-manager.ts +2 -2
- package/ts/proxies/smart-proxy/route-connection-handler.ts +23 -307
- package/ts/proxies/smart-proxy/smart-proxy.ts +25 -25
- package/ts/routing/index.ts +9 -0
- package/ts/routing/models/http-types.ts +6 -0
- package/ts/{http → routing}/router/proxy-router.ts +1 -1
- package/ts/{http → routing}/router/route-router.ts +1 -1
- package/dist_ts/certificate/acme/acme-factory.d.ts +0 -17
- package/dist_ts/certificate/acme/acme-factory.js +0 -40
- package/dist_ts/certificate/acme/challenge-handler.d.ts +0 -44
- package/dist_ts/certificate/acme/challenge-handler.js +0 -92
- package/dist_ts/certificate/acme/index.d.ts +0 -4
- package/dist_ts/certificate/acme/index.js +0 -5
- package/dist_ts/certificate/certificate-manager.d.ts +0 -150
- package/dist_ts/certificate/certificate-manager.js +0 -505
- package/dist_ts/certificate/events/certificate-events.d.ts +0 -33
- package/dist_ts/certificate/events/certificate-events.js +0 -38
- package/dist_ts/certificate/events/simplified-events.d.ts +0 -56
- package/dist_ts/certificate/events/simplified-events.js +0 -13
- package/dist_ts/certificate/index.d.ts +0 -30
- package/dist_ts/certificate/index.js +0 -37
- package/dist_ts/certificate/models/certificate-errors.d.ts +0 -69
- package/dist_ts/certificate/models/certificate-errors.js +0 -141
- package/dist_ts/certificate/models/certificate-strategy.d.ts +0 -60
- package/dist_ts/certificate/models/certificate-strategy.js +0 -73
- package/dist_ts/certificate/models/certificate-types.d.ts +0 -97
- package/dist_ts/certificate/models/certificate-types.js +0 -2
- package/dist_ts/certificate/providers/cert-provisioner.d.ts +0 -119
- package/dist_ts/certificate/providers/cert-provisioner.js +0 -422
- package/dist_ts/certificate/providers/index.d.ts +0 -4
- package/dist_ts/certificate/providers/index.js +0 -5
- package/dist_ts/certificate/simplified-certificate-manager.d.ts +0 -150
- package/dist_ts/certificate/simplified-certificate-manager.js +0 -501
- package/dist_ts/certificate/storage/file-storage.d.ts +0 -66
- package/dist_ts/certificate/storage/file-storage.js +0 -194
- package/dist_ts/certificate/storage/index.d.ts +0 -4
- package/dist_ts/certificate/storage/index.js +0 -5
- package/dist_ts/certificate/utils/certificate-helpers.d.ts +0 -17
- package/dist_ts/certificate/utils/certificate-helpers.js +0 -45
- package/dist_ts/classes.iptablesproxy.d.ts +0 -112
- package/dist_ts/classes.iptablesproxy.js +0 -765
- package/dist_ts/classes.networkproxy.d.ts +0 -243
- package/dist_ts/classes.networkproxy.js +0 -1424
- package/dist_ts/classes.nftablesproxy.d.ts +0 -219
- package/dist_ts/classes.nftablesproxy.js +0 -1542
- package/dist_ts/classes.port80handler.d.ts +0 -215
- package/dist_ts/classes.port80handler.js +0 -736
- package/dist_ts/classes.portproxy.d.ts +0 -171
- package/dist_ts/classes.portproxy.js +0 -1802
- package/dist_ts/classes.pp.acmemanager.d.ts +0 -34
- package/dist_ts/classes.pp.acmemanager.js +0 -123
- package/dist_ts/classes.pp.connectionhandler.d.ts +0 -39
- package/dist_ts/classes.pp.connectionhandler.js +0 -754
- package/dist_ts/classes.pp.connectionmanager.d.ts +0 -78
- package/dist_ts/classes.pp.connectionmanager.js +0 -378
- package/dist_ts/classes.pp.domainconfigmanager.d.ts +0 -55
- package/dist_ts/classes.pp.domainconfigmanager.js +0 -103
- package/dist_ts/classes.pp.interfaces.d.ts +0 -133
- package/dist_ts/classes.pp.interfaces.js +0 -2
- package/dist_ts/classes.pp.networkproxybridge.d.ts +0 -57
- package/dist_ts/classes.pp.networkproxybridge.js +0 -306
- package/dist_ts/classes.pp.portproxy.d.ts +0 -64
- package/dist_ts/classes.pp.portproxy.js +0 -567
- package/dist_ts/classes.pp.portrangemanager.d.ts +0 -56
- package/dist_ts/classes.pp.portrangemanager.js +0 -179
- package/dist_ts/classes.pp.securitymanager.d.ts +0 -47
- package/dist_ts/classes.pp.securitymanager.js +0 -126
- package/dist_ts/classes.pp.snihandler.d.ts +0 -153
- package/dist_ts/classes.pp.snihandler.js +0 -1053
- package/dist_ts/classes.pp.timeoutmanager.d.ts +0 -47
- package/dist_ts/classes.pp.timeoutmanager.js +0 -154
- package/dist_ts/classes.pp.tlsalert.d.ts +0 -149
- package/dist_ts/classes.pp.tlsalert.js +0 -225
- package/dist_ts/classes.pp.tlsmanager.d.ts +0 -57
- package/dist_ts/classes.pp.tlsmanager.js +0 -132
- package/dist_ts/classes.snihandler.d.ts +0 -198
- package/dist_ts/classes.snihandler.js +0 -1210
- package/dist_ts/classes.sslredirect.d.ts +0 -8
- package/dist_ts/classes.sslredirect.js +0 -28
- package/dist_ts/common/acmeFactory.d.ts +0 -9
- package/dist_ts/common/acmeFactory.js +0 -20
- package/dist_ts/common/port80-adapter.d.ts +0 -11
- package/dist_ts/common/port80-adapter.js +0 -87
- package/dist_ts/examples/forwarding-example.d.ts +0 -1
- package/dist_ts/examples/forwarding-example.js +0 -96
- package/dist_ts/forwarding/config/domain-config.d.ts +0 -12
- package/dist_ts/forwarding/config/domain-config.js +0 -12
- package/dist_ts/forwarding/config/domain-manager.d.ts +0 -86
- package/dist_ts/forwarding/config/domain-manager.js +0 -242
- package/dist_ts/helpers.certificates.d.ts +0 -5
- package/dist_ts/helpers.certificates.js +0 -23
- package/dist_ts/http/port80/acme-interfaces.d.ts +0 -108
- package/dist_ts/http/port80/acme-interfaces.js +0 -51
- package/dist_ts/http/port80/challenge-responder.d.ts +0 -53
- package/dist_ts/http/port80/challenge-responder.js +0 -203
- package/dist_ts/http/port80/index.d.ts +0 -6
- package/dist_ts/http/port80/index.js +0 -9
- package/dist_ts/http/port80/port80-handler.d.ts +0 -136
- package/dist_ts/http/port80/port80-handler.js +0 -592
- package/dist_ts/http/redirects/index.d.ts +0 -4
- package/dist_ts/http/redirects/index.js +0 -5
- package/dist_ts/networkproxy/classes.np.certificatemanager.d.ts +0 -77
- package/dist_ts/networkproxy/classes.np.certificatemanager.js +0 -372
- package/dist_ts/networkproxy/classes.np.connectionpool.d.ts +0 -47
- package/dist_ts/networkproxy/classes.np.connectionpool.js +0 -210
- package/dist_ts/networkproxy/classes.np.networkproxy.d.ts +0 -118
- package/dist_ts/networkproxy/classes.np.networkproxy.js +0 -387
- package/dist_ts/networkproxy/classes.np.requesthandler.d.ts +0 -56
- package/dist_ts/networkproxy/classes.np.requesthandler.js +0 -393
- package/dist_ts/networkproxy/classes.np.types.d.ts +0 -83
- package/dist_ts/networkproxy/classes.np.types.js +0 -35
- package/dist_ts/networkproxy/classes.np.websockethandler.d.ts +0 -38
- package/dist_ts/networkproxy/classes.np.websockethandler.js +0 -188
- package/dist_ts/networkproxy/index.d.ts +0 -1
- package/dist_ts/networkproxy/index.js +0 -4
- package/dist_ts/nfttablesproxy/classes.nftablesproxy.d.ts +0 -219
- package/dist_ts/nfttablesproxy/classes.nftablesproxy.js +0 -1542
- package/dist_ts/port80handler/classes.port80handler.d.ts +0 -10
- package/dist_ts/port80handler/classes.port80handler.js +0 -16
- package/dist_ts/proxies/network-proxy/connection-pool.js +0 -210
- package/dist_ts/proxies/network-proxy/context-creator.js +0 -108
- package/dist_ts/proxies/network-proxy/http2-request-handler.js +0 -201
- package/dist_ts/proxies/network-proxy/index.js +0 -12
- package/dist_ts/proxies/network-proxy/models/index.d.ts +0 -4
- package/dist_ts/proxies/network-proxy/models/index.js +0 -5
- package/dist_ts/proxies/network-proxy/models/types.js +0 -276
- package/dist_ts/proxies/network-proxy/security-manager.js +0 -255
- package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.d.ts +0 -48
- package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.js +0 -76
- package/dist_ts/proxies/smart-proxy/connection-handler.d.ts +0 -39
- package/dist_ts/proxies/smart-proxy/connection-handler.js +0 -894
- package/dist_ts/proxies/smart-proxy/domain-config-manager.d.ts +0 -110
- package/dist_ts/proxies/smart-proxy/domain-config-manager.js +0 -386
- package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.d.ts +0 -168
- package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.js +0 -642
- package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.d.ts +0 -65
- package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.js +0 -31
- package/dist_ts/proxies/smart-proxy/models/smartproxy-options.d.ts +0 -102
- package/dist_ts/proxies/smart-proxy/models/smartproxy-options.js +0 -73
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +0 -41
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +0 -121
- package/dist_ts/proxies/smart-proxy/port-range-manager.d.ts +0 -56
- package/dist_ts/proxies/smart-proxy/port-range-manager.js +0 -176
- package/dist_ts/proxies/smart-proxy/route-helpers/index.d.ts +0 -9
- package/dist_ts/proxies/smart-proxy/route-helpers/index.js +0 -11
- package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +0 -7
- package/dist_ts/proxies/smart-proxy/route-helpers.js +0 -9
- package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.d.ts +0 -41
- package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.js +0 -132
- package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.d.ts +0 -51
- package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.js +0 -124
- package/dist_ts/redirect/classes.redirect.d.ts +0 -96
- package/dist_ts/redirect/classes.redirect.js +0 -194
- package/dist_ts/smartproxy/classes.pp.certprovisioner.d.ts +0 -54
- package/dist_ts/smartproxy/classes.pp.certprovisioner.js +0 -179
- package/dist_ts/smartproxy/classes.pp.connectionhandler.d.ts +0 -39
- package/dist_ts/smartproxy/classes.pp.connectionhandler.js +0 -894
- package/dist_ts/smartproxy/classes.pp.connectionmanager.d.ts +0 -78
- package/dist_ts/smartproxy/classes.pp.connectionmanager.js +0 -378
- package/dist_ts/smartproxy/classes.pp.domainconfigmanager.d.ts +0 -94
- package/dist_ts/smartproxy/classes.pp.domainconfigmanager.js +0 -255
- package/dist_ts/smartproxy/classes.pp.interfaces.d.ts +0 -103
- package/dist_ts/smartproxy/classes.pp.interfaces.js +0 -2
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +0 -62
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +0 -316
- package/dist_ts/smartproxy/classes.pp.portrangemanager.d.ts +0 -56
- package/dist_ts/smartproxy/classes.pp.portrangemanager.js +0 -176
- package/dist_ts/smartproxy/classes.pp.securitymanager.d.ts +0 -64
- package/dist_ts/smartproxy/classes.pp.securitymanager.js +0 -149
- package/dist_ts/smartproxy/classes.pp.snihandler.d.ts +0 -153
- package/dist_ts/smartproxy/classes.pp.snihandler.js +0 -1053
- package/dist_ts/smartproxy/classes.pp.timeoutmanager.d.ts +0 -47
- package/dist_ts/smartproxy/classes.pp.timeoutmanager.js +0 -154
- package/dist_ts/smartproxy/classes.pp.tlsalert.d.ts +0 -149
- package/dist_ts/smartproxy/classes.pp.tlsalert.js +0 -225
- package/dist_ts/smartproxy/classes.pp.tlsmanager.d.ts +0 -57
- package/dist_ts/smartproxy/classes.pp.tlsmanager.js +0 -132
- package/dist_ts/smartproxy/classes.smartproxy.d.ts +0 -63
- package/dist_ts/smartproxy/classes.smartproxy.js +0 -521
- package/dist_ts/smartproxy/forwarding/domain-config.d.ts +0 -12
- package/dist_ts/smartproxy/forwarding/domain-config.js +0 -12
- package/dist_ts/smartproxy/forwarding/domain-manager.d.ts +0 -86
- package/dist_ts/smartproxy/forwarding/domain-manager.js +0 -241
- package/dist_ts/smartproxy/forwarding/forwarding.factory.d.ts +0 -24
- package/dist_ts/smartproxy/forwarding/forwarding.factory.js +0 -137
- package/dist_ts/smartproxy/forwarding/forwarding.handler.d.ts +0 -55
- package/dist_ts/smartproxy/forwarding/forwarding.handler.js +0 -94
- package/dist_ts/smartproxy/forwarding/http.handler.d.ts +0 -25
- package/dist_ts/smartproxy/forwarding/http.handler.js +0 -123
- package/dist_ts/smartproxy/forwarding/https-passthrough.handler.d.ts +0 -24
- package/dist_ts/smartproxy/forwarding/https-passthrough.handler.js +0 -154
- package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.d.ts +0 -36
- package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.js +0 -229
- package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.d.ts +0 -35
- package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.js +0 -254
- package/dist_ts/smartproxy/forwarding/index.d.ts +0 -16
- package/dist_ts/smartproxy/forwarding/index.js +0 -23
- package/dist_ts/smartproxy/types/forwarding.types.d.ts +0 -104
- package/dist_ts/smartproxy/types/forwarding.types.js +0 -50
- package/dist_ts/smartproxy.classes.networkproxy.d.ts +0 -31
- package/dist_ts/smartproxy.classes.networkproxy.js +0 -305
- package/dist_ts/smartproxy.classes.router.d.ts +0 -13
- package/dist_ts/smartproxy.classes.router.js +0 -33
- package/dist_ts/smartproxy.classes.sslredirect.d.ts +0 -8
- package/dist_ts/smartproxy.classes.sslredirect.js +0 -28
- package/dist_ts/smartproxy.helpers.certificates.d.ts +0 -5
- package/dist_ts/smartproxy.helpers.certificates.js +0 -23
- package/dist_ts/smartproxy.plugins.d.ts +0 -18
- package/dist_ts/smartproxy.plugins.js +0 -23
- package/dist_ts/smartproxy.portproxy.d.ts +0 -26
- package/dist_ts/smartproxy.portproxy.js +0 -295
- package/ts/http/index.ts +0 -16
- package/ts/http/models/http-types.ts +0 -108
- package/ts/http/redirects/index.ts +0 -3
- package/ts/proxies/network-proxy/models/index.ts +0 -4
- package/ts/redirect/classes.redirect.ts +0 -295
- /package/dist_ts/proxies/{network-proxy → http-proxy}/context-creator.d.ts +0 -0
- /package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.d.ts +0 -0
- /package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.d.ts +0 -0
- /package/dist_ts/proxies/{network-proxy → http-proxy}/http2-request-handler.d.ts +0 -0
- /package/dist_ts/proxies/{network-proxy → http-proxy}/security-manager.d.ts +0 -0
- /package/ts/proxies/{network-proxy → http-proxy}/context-creator.ts +0 -0
- /package/ts/proxies/{network-proxy → http-proxy}/function-cache.ts +0 -0
- /package/ts/proxies/{network-proxy → http-proxy}/http-request-handler.ts +0 -0
- /package/ts/proxies/{network-proxy → http-proxy}/http2-request-handler.ts +0 -0
- /package/ts/proxies/{network-proxy → http-proxy}/security-manager.ts +0 -0
- /package/ts/{http → routing}/router/index.ts +0 -0
|
@@ -1,642 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../../plugins.js';
|
|
2
|
-
// Importing required components
|
|
3
|
-
import { ConnectionManager } from './connection-manager.js';
|
|
4
|
-
import { SecurityManager } from './security-manager.js';
|
|
5
|
-
import { TlsManager } from './tls-manager.js';
|
|
6
|
-
import { NetworkProxyBridge } from './network-proxy-bridge.js';
|
|
7
|
-
import { TimeoutManager } from './timeout-manager.js';
|
|
8
|
-
import { PortManager } from './port-manager.js';
|
|
9
|
-
import { RouteManager } from './route-manager.js';
|
|
10
|
-
import { RouteConnectionHandler } from './route-connection-handler.js';
|
|
11
|
-
import { NFTablesManager } from './nftables-manager.js';
|
|
12
|
-
// External dependencies
|
|
13
|
-
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
|
14
|
-
import { CertProvisioner } from '../../certificate/providers/cert-provisioner.js';
|
|
15
|
-
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
|
16
|
-
import { createPort80HandlerOptions } from '../../common/port80-adapter.js';
|
|
17
|
-
/**
|
|
18
|
-
* SmartProxy - Pure route-based API
|
|
19
|
-
*
|
|
20
|
-
* SmartProxy is a unified proxy system that works with routes to define connection handling behavior.
|
|
21
|
-
* Each route contains matching criteria (ports, domains, etc.) and an action to take (forward, redirect, block).
|
|
22
|
-
*
|
|
23
|
-
* Configuration is provided through a set of routes, with each route defining:
|
|
24
|
-
* - What to match (ports, domains, paths, client IPs)
|
|
25
|
-
* - What to do with matching traffic (forward, redirect, block)
|
|
26
|
-
* - How to handle TLS (passthrough, terminate, terminate-and-reencrypt)
|
|
27
|
-
* - Security settings (IP restrictions, connection limits)
|
|
28
|
-
* - Advanced options (timeout, headers, etc.)
|
|
29
|
-
*/
|
|
30
|
-
export class SmartProxy extends plugins.EventEmitter {
|
|
31
|
-
/**
|
|
32
|
-
* Constructor for SmartProxy
|
|
33
|
-
*
|
|
34
|
-
* @param settingsArg Configuration options containing routes and other settings
|
|
35
|
-
* Routes define how traffic is matched and handled, with each route having:
|
|
36
|
-
* - match: criteria for matching traffic (ports, domains, paths, IPs)
|
|
37
|
-
* - action: what to do with matched traffic (forward, redirect, block)
|
|
38
|
-
*
|
|
39
|
-
* Example:
|
|
40
|
-
* ```ts
|
|
41
|
-
* const proxy = new SmartProxy({
|
|
42
|
-
* routes: [
|
|
43
|
-
* {
|
|
44
|
-
* match: {
|
|
45
|
-
* ports: 443,
|
|
46
|
-
* domains: ['example.com', '*.example.com']
|
|
47
|
-
* },
|
|
48
|
-
* action: {
|
|
49
|
-
* type: 'forward',
|
|
50
|
-
* target: { host: '10.0.0.1', port: 8443 },
|
|
51
|
-
* tls: { mode: 'passthrough' }
|
|
52
|
-
* }
|
|
53
|
-
* }
|
|
54
|
-
* ],
|
|
55
|
-
* defaults: {
|
|
56
|
-
* target: { host: 'localhost', port: 8080 },
|
|
57
|
-
* security: { ipAllowList: ['*'] }
|
|
58
|
-
* }
|
|
59
|
-
* });
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
constructor(settingsArg) {
|
|
63
|
-
super();
|
|
64
|
-
this.connectionLogger = null;
|
|
65
|
-
this.isShuttingDown = false;
|
|
66
|
-
// Port80Handler for ACME certificate management
|
|
67
|
-
this.port80Handler = null;
|
|
68
|
-
// Set reasonable defaults for all settings
|
|
69
|
-
this.settings = {
|
|
70
|
-
...settingsArg,
|
|
71
|
-
initialDataTimeout: settingsArg.initialDataTimeout || 120000,
|
|
72
|
-
socketTimeout: settingsArg.socketTimeout || 3600000,
|
|
73
|
-
inactivityCheckInterval: settingsArg.inactivityCheckInterval || 60000,
|
|
74
|
-
maxConnectionLifetime: settingsArg.maxConnectionLifetime || 86400000,
|
|
75
|
-
inactivityTimeout: settingsArg.inactivityTimeout || 14400000,
|
|
76
|
-
gracefulShutdownTimeout: settingsArg.gracefulShutdownTimeout || 30000,
|
|
77
|
-
noDelay: settingsArg.noDelay !== undefined ? settingsArg.noDelay : true,
|
|
78
|
-
keepAlive: settingsArg.keepAlive !== undefined ? settingsArg.keepAlive : true,
|
|
79
|
-
keepAliveInitialDelay: settingsArg.keepAliveInitialDelay || 10000,
|
|
80
|
-
maxPendingDataSize: settingsArg.maxPendingDataSize || 10 * 1024 * 1024,
|
|
81
|
-
disableInactivityCheck: settingsArg.disableInactivityCheck || false,
|
|
82
|
-
enableKeepAliveProbes: settingsArg.enableKeepAliveProbes !== undefined ? settingsArg.enableKeepAliveProbes : true,
|
|
83
|
-
enableDetailedLogging: settingsArg.enableDetailedLogging || false,
|
|
84
|
-
enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false,
|
|
85
|
-
enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false,
|
|
86
|
-
allowSessionTicket: settingsArg.allowSessionTicket !== undefined ? settingsArg.allowSessionTicket : true,
|
|
87
|
-
maxConnectionsPerIP: settingsArg.maxConnectionsPerIP || 100,
|
|
88
|
-
connectionRateLimitPerMinute: settingsArg.connectionRateLimitPerMinute || 300,
|
|
89
|
-
keepAliveTreatment: settingsArg.keepAliveTreatment || 'extended',
|
|
90
|
-
keepAliveInactivityMultiplier: settingsArg.keepAliveInactivityMultiplier || 6,
|
|
91
|
-
extendedKeepAliveLifetime: settingsArg.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000,
|
|
92
|
-
networkProxyPort: settingsArg.networkProxyPort || 8443,
|
|
93
|
-
};
|
|
94
|
-
// Set default ACME options if not provided
|
|
95
|
-
this.settings.acme = this.settings.acme || {};
|
|
96
|
-
if (Object.keys(this.settings.acme).length === 0) {
|
|
97
|
-
this.settings.acme = {
|
|
98
|
-
enabled: false,
|
|
99
|
-
port: 80,
|
|
100
|
-
accountEmail: 'admin@example.com',
|
|
101
|
-
useProduction: false,
|
|
102
|
-
renewThresholdDays: 30,
|
|
103
|
-
autoRenew: true,
|
|
104
|
-
certificateStore: './certs',
|
|
105
|
-
skipConfiguredCerts: false,
|
|
106
|
-
httpsRedirectPort: 443,
|
|
107
|
-
renewCheckIntervalHours: 24,
|
|
108
|
-
routeForwards: []
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
// Initialize component managers
|
|
112
|
-
this.timeoutManager = new TimeoutManager(this.settings);
|
|
113
|
-
this.securityManager = new SecurityManager(this.settings);
|
|
114
|
-
this.connectionManager = new ConnectionManager(this.settings, this.securityManager, this.timeoutManager);
|
|
115
|
-
// Create the route manager
|
|
116
|
-
this.routeManager = new RouteManager(this.settings);
|
|
117
|
-
// Create other required components
|
|
118
|
-
this.tlsManager = new TlsManager(this.settings);
|
|
119
|
-
this.networkProxyBridge = new NetworkProxyBridge(this.settings);
|
|
120
|
-
// Initialize connection handler with route support
|
|
121
|
-
this.routeConnectionHandler = new RouteConnectionHandler(this.settings, this.connectionManager, this.securityManager, this.tlsManager, this.networkProxyBridge, this.timeoutManager, this.routeManager);
|
|
122
|
-
// Initialize port manager
|
|
123
|
-
this.portManager = new PortManager(this.settings, this.routeConnectionHandler);
|
|
124
|
-
// Initialize NFTablesManager
|
|
125
|
-
this.nftablesManager = new NFTablesManager(this.settings);
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Initialize the Port80Handler for ACME certificate management
|
|
129
|
-
*/
|
|
130
|
-
async initializePort80Handler() {
|
|
131
|
-
const config = this.settings.acme;
|
|
132
|
-
if (!config.enabled) {
|
|
133
|
-
console.log('ACME is disabled in configuration');
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
try {
|
|
137
|
-
// Build and start the Port80Handler
|
|
138
|
-
this.port80Handler = buildPort80Handler({
|
|
139
|
-
...config,
|
|
140
|
-
httpsRedirectPort: config.httpsRedirectPort || 443
|
|
141
|
-
});
|
|
142
|
-
// Share Port80Handler with NetworkProxyBridge before start
|
|
143
|
-
this.networkProxyBridge.setPort80Handler(this.port80Handler);
|
|
144
|
-
await this.port80Handler.start();
|
|
145
|
-
console.log(`Port80Handler started on port ${config.port}`);
|
|
146
|
-
}
|
|
147
|
-
catch (err) {
|
|
148
|
-
console.log(`Error initializing Port80Handler: ${err}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Start the proxy server with support for both configuration types
|
|
153
|
-
*/
|
|
154
|
-
async start() {
|
|
155
|
-
// Don't start if already shutting down
|
|
156
|
-
if (this.isShuttingDown) {
|
|
157
|
-
console.log("Cannot start SmartProxy while it's shutting down");
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
// Pure route-based configuration - no domain configs needed
|
|
161
|
-
// Initialize Port80Handler if enabled
|
|
162
|
-
await this.initializePort80Handler();
|
|
163
|
-
// Initialize CertProvisioner for unified certificate workflows
|
|
164
|
-
if (this.port80Handler) {
|
|
165
|
-
const acme = this.settings.acme;
|
|
166
|
-
// Setup route forwards
|
|
167
|
-
const routeForwards = acme.routeForwards?.map(f => f) || [];
|
|
168
|
-
// Create CertProvisioner with appropriate parameters
|
|
169
|
-
// No longer need to support multiple configuration types
|
|
170
|
-
// Just pass the routes directly
|
|
171
|
-
this.certProvisioner = new CertProvisioner(this.settings.routes, this.port80Handler, this.networkProxyBridge, this.settings.certProvisionFunction, acme.renewThresholdDays, acme.renewCheckIntervalHours, acme.autoRenew, routeForwards);
|
|
172
|
-
// Register certificate event handler
|
|
173
|
-
this.certProvisioner.on('certificate', (certData) => {
|
|
174
|
-
this.emit('certificate', {
|
|
175
|
-
domain: certData.domain,
|
|
176
|
-
publicKey: certData.certificate,
|
|
177
|
-
privateKey: certData.privateKey,
|
|
178
|
-
expiryDate: certData.expiryDate,
|
|
179
|
-
source: certData.source,
|
|
180
|
-
isRenewal: certData.isRenewal
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
await this.certProvisioner.start();
|
|
184
|
-
console.log('CertProvisioner started');
|
|
185
|
-
}
|
|
186
|
-
// Initialize and start NetworkProxy if needed
|
|
187
|
-
if (this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0) {
|
|
188
|
-
await this.networkProxyBridge.initialize();
|
|
189
|
-
await this.networkProxyBridge.start();
|
|
190
|
-
}
|
|
191
|
-
// Validate the route configuration
|
|
192
|
-
const configWarnings = this.routeManager.validateConfiguration();
|
|
193
|
-
if (configWarnings.length > 0) {
|
|
194
|
-
console.log("Route configuration warnings:");
|
|
195
|
-
for (const warning of configWarnings) {
|
|
196
|
-
console.log(` - ${warning}`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
// Get listening ports from RouteManager
|
|
200
|
-
const listeningPorts = this.routeManager.getListeningPorts();
|
|
201
|
-
// Provision NFTables rules for routes that use NFTables
|
|
202
|
-
for (const route of this.settings.routes) {
|
|
203
|
-
if (route.action.forwardingEngine === 'nftables') {
|
|
204
|
-
await this.nftablesManager.provisionRoute(route);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
// Start port listeners using the PortManager
|
|
208
|
-
await this.portManager.addPorts(listeningPorts);
|
|
209
|
-
// Set up periodic connection logging and inactivity checks
|
|
210
|
-
this.connectionLogger = setInterval(() => {
|
|
211
|
-
// Immediately return if shutting down
|
|
212
|
-
if (this.isShuttingDown)
|
|
213
|
-
return;
|
|
214
|
-
// Perform inactivity check
|
|
215
|
-
this.connectionManager.performInactivityCheck();
|
|
216
|
-
// Log connection statistics
|
|
217
|
-
const now = Date.now();
|
|
218
|
-
let maxIncoming = 0;
|
|
219
|
-
let maxOutgoing = 0;
|
|
220
|
-
let tlsConnections = 0;
|
|
221
|
-
let nonTlsConnections = 0;
|
|
222
|
-
let completedTlsHandshakes = 0;
|
|
223
|
-
let pendingTlsHandshakes = 0;
|
|
224
|
-
let keepAliveConnections = 0;
|
|
225
|
-
let networkProxyConnections = 0;
|
|
226
|
-
// Get connection records for analysis
|
|
227
|
-
const connectionRecords = this.connectionManager.getConnections();
|
|
228
|
-
// Analyze active connections
|
|
229
|
-
for (const record of connectionRecords.values()) {
|
|
230
|
-
// Track connection stats
|
|
231
|
-
if (record.isTLS) {
|
|
232
|
-
tlsConnections++;
|
|
233
|
-
if (record.tlsHandshakeComplete) {
|
|
234
|
-
completedTlsHandshakes++;
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
pendingTlsHandshakes++;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
nonTlsConnections++;
|
|
242
|
-
}
|
|
243
|
-
if (record.hasKeepAlive) {
|
|
244
|
-
keepAliveConnections++;
|
|
245
|
-
}
|
|
246
|
-
if (record.usingNetworkProxy) {
|
|
247
|
-
networkProxyConnections++;
|
|
248
|
-
}
|
|
249
|
-
maxIncoming = Math.max(maxIncoming, now - record.incomingStartTime);
|
|
250
|
-
if (record.outgoingStartTime) {
|
|
251
|
-
maxOutgoing = Math.max(maxOutgoing, now - record.outgoingStartTime);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
// Get termination stats
|
|
255
|
-
const terminationStats = this.connectionManager.getTerminationStats();
|
|
256
|
-
// Log detailed stats
|
|
257
|
-
console.log(`Active connections: ${connectionRecords.size}. ` +
|
|
258
|
-
`Types: TLS=${tlsConnections} (Completed=${completedTlsHandshakes}, Pending=${pendingTlsHandshakes}), ` +
|
|
259
|
-
`Non-TLS=${nonTlsConnections}, KeepAlive=${keepAliveConnections}, NetworkProxy=${networkProxyConnections}. ` +
|
|
260
|
-
`Longest running: IN=${plugins.prettyMs(maxIncoming)}, OUT=${plugins.prettyMs(maxOutgoing)}. ` +
|
|
261
|
-
`Termination stats: ${JSON.stringify({
|
|
262
|
-
IN: terminationStats.incoming,
|
|
263
|
-
OUT: terminationStats.outgoing,
|
|
264
|
-
})}`);
|
|
265
|
-
}, this.settings.inactivityCheckInterval || 60000);
|
|
266
|
-
// Make sure the interval doesn't keep the process alive
|
|
267
|
-
if (this.connectionLogger.unref) {
|
|
268
|
-
this.connectionLogger.unref();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Extract domain configurations from routes for certificate provisioning
|
|
273
|
-
*
|
|
274
|
-
* Note: This method has been removed as we now work directly with routes
|
|
275
|
-
*/
|
|
276
|
-
/**
|
|
277
|
-
* Stop the proxy server
|
|
278
|
-
*/
|
|
279
|
-
async stop() {
|
|
280
|
-
console.log('SmartProxy shutting down...');
|
|
281
|
-
this.isShuttingDown = true;
|
|
282
|
-
this.portManager.setShuttingDown(true);
|
|
283
|
-
// Stop CertProvisioner if active
|
|
284
|
-
if (this.certProvisioner) {
|
|
285
|
-
await this.certProvisioner.stop();
|
|
286
|
-
console.log('CertProvisioner stopped');
|
|
287
|
-
}
|
|
288
|
-
// Stop NFTablesManager
|
|
289
|
-
await this.nftablesManager.stop();
|
|
290
|
-
console.log('NFTablesManager stopped');
|
|
291
|
-
// Stop the Port80Handler if running
|
|
292
|
-
if (this.port80Handler) {
|
|
293
|
-
try {
|
|
294
|
-
await this.port80Handler.stop();
|
|
295
|
-
console.log('Port80Handler stopped');
|
|
296
|
-
this.port80Handler = null;
|
|
297
|
-
}
|
|
298
|
-
catch (err) {
|
|
299
|
-
console.log(`Error stopping Port80Handler: ${err}`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
// Stop the connection logger
|
|
303
|
-
if (this.connectionLogger) {
|
|
304
|
-
clearInterval(this.connectionLogger);
|
|
305
|
-
this.connectionLogger = null;
|
|
306
|
-
}
|
|
307
|
-
// Stop all port listeners
|
|
308
|
-
await this.portManager.closeAll();
|
|
309
|
-
console.log('All servers closed. Cleaning up active connections...');
|
|
310
|
-
// Clean up all active connections
|
|
311
|
-
this.connectionManager.clearConnections();
|
|
312
|
-
// Stop NetworkProxy
|
|
313
|
-
await this.networkProxyBridge.stop();
|
|
314
|
-
console.log('SmartProxy shutdown complete.');
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Updates the domain configurations for the proxy
|
|
318
|
-
*
|
|
319
|
-
* Note: This legacy method has been removed. Use updateRoutes instead.
|
|
320
|
-
*/
|
|
321
|
-
async updateDomainConfigs() {
|
|
322
|
-
console.warn('Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
|
|
323
|
-
throw new Error('updateDomainConfigs() is deprecated - use updateRoutes() instead');
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Update routes with new configuration
|
|
327
|
-
*
|
|
328
|
-
* This method replaces the current route configuration with the provided routes.
|
|
329
|
-
* It also provisions certificates for routes that require TLS termination and have
|
|
330
|
-
* `certificate: 'auto'` set in their TLS configuration.
|
|
331
|
-
*
|
|
332
|
-
* @param newRoutes Array of route configurations to use
|
|
333
|
-
*
|
|
334
|
-
* Example:
|
|
335
|
-
* ```ts
|
|
336
|
-
* proxy.updateRoutes([
|
|
337
|
-
* {
|
|
338
|
-
* match: { ports: 443, domains: 'secure.example.com' },
|
|
339
|
-
* action: {
|
|
340
|
-
* type: 'forward',
|
|
341
|
-
* target: { host: '10.0.0.1', port: 8443 },
|
|
342
|
-
* tls: { mode: 'terminate', certificate: 'auto' }
|
|
343
|
-
* }
|
|
344
|
-
* }
|
|
345
|
-
* ]);
|
|
346
|
-
* ```
|
|
347
|
-
*/
|
|
348
|
-
async updateRoutes(newRoutes) {
|
|
349
|
-
console.log(`Updating routes (${newRoutes.length} routes)`);
|
|
350
|
-
// Get existing routes that use NFTables
|
|
351
|
-
const oldNfTablesRoutes = this.settings.routes.filter(r => r.action.forwardingEngine === 'nftables');
|
|
352
|
-
// Get new routes that use NFTables
|
|
353
|
-
const newNfTablesRoutes = newRoutes.filter(r => r.action.forwardingEngine === 'nftables');
|
|
354
|
-
// Find routes to remove, update, or add
|
|
355
|
-
for (const oldRoute of oldNfTablesRoutes) {
|
|
356
|
-
const newRoute = newNfTablesRoutes.find(r => r.name === oldRoute.name);
|
|
357
|
-
if (!newRoute) {
|
|
358
|
-
// Route was removed
|
|
359
|
-
await this.nftablesManager.deprovisionRoute(oldRoute);
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
// Route was updated
|
|
363
|
-
await this.nftablesManager.updateRoute(oldRoute, newRoute);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// Find new routes to add
|
|
367
|
-
for (const newRoute of newNfTablesRoutes) {
|
|
368
|
-
const oldRoute = oldNfTablesRoutes.find(r => r.name === newRoute.name);
|
|
369
|
-
if (!oldRoute) {
|
|
370
|
-
// New route
|
|
371
|
-
await this.nftablesManager.provisionRoute(newRoute);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
// Update routes in RouteManager
|
|
375
|
-
this.routeManager.updateRoutes(newRoutes);
|
|
376
|
-
// Get the new set of required ports
|
|
377
|
-
const requiredPorts = this.routeManager.getListeningPorts();
|
|
378
|
-
// Update port listeners to match the new configuration
|
|
379
|
-
await this.portManager.updatePorts(requiredPorts);
|
|
380
|
-
// Update settings with the new routes
|
|
381
|
-
this.settings.routes = newRoutes;
|
|
382
|
-
// If NetworkProxy is initialized, resync the configurations
|
|
383
|
-
if (this.networkProxyBridge.getNetworkProxy()) {
|
|
384
|
-
await this.networkProxyBridge.syncRoutesToNetworkProxy(newRoutes);
|
|
385
|
-
}
|
|
386
|
-
// If Port80Handler is running, provision certificates based on routes
|
|
387
|
-
if (this.port80Handler && this.settings.acme?.enabled) {
|
|
388
|
-
// Register all eligible domains from routes
|
|
389
|
-
this.port80Handler.addDomainsFromRoutes(newRoutes);
|
|
390
|
-
// Handle static certificates from certProvisionFunction if available
|
|
391
|
-
if (this.settings.certProvisionFunction) {
|
|
392
|
-
for (const route of newRoutes) {
|
|
393
|
-
// Skip routes without domains
|
|
394
|
-
if (!route.match.domains)
|
|
395
|
-
continue;
|
|
396
|
-
// Skip non-forward routes
|
|
397
|
-
if (route.action.type !== 'forward')
|
|
398
|
-
continue;
|
|
399
|
-
// Skip routes without TLS termination
|
|
400
|
-
if (!route.action.tls ||
|
|
401
|
-
route.action.tls.mode === 'passthrough' ||
|
|
402
|
-
!route.action.target)
|
|
403
|
-
continue;
|
|
404
|
-
// Skip certificate provisioning if certificate is not auto
|
|
405
|
-
if (route.action.tls.certificate !== 'auto')
|
|
406
|
-
continue;
|
|
407
|
-
const domains = Array.isArray(route.match.domains)
|
|
408
|
-
? route.match.domains
|
|
409
|
-
: [route.match.domains];
|
|
410
|
-
for (const domain of domains) {
|
|
411
|
-
try {
|
|
412
|
-
const provision = await this.settings.certProvisionFunction(domain);
|
|
413
|
-
// Skip http01 as those are handled by Port80Handler
|
|
414
|
-
if (provision !== 'http01') {
|
|
415
|
-
// Handle static certificate (e.g., DNS-01 provisioned)
|
|
416
|
-
const certObj = provision;
|
|
417
|
-
const certData = {
|
|
418
|
-
domain: certObj.domainName,
|
|
419
|
-
certificate: certObj.publicKey,
|
|
420
|
-
privateKey: certObj.privateKey,
|
|
421
|
-
expiryDate: new Date(certObj.validUntil),
|
|
422
|
-
routeReference: {
|
|
423
|
-
routeName: route.name
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
this.networkProxyBridge.applyExternalCertificate(certData);
|
|
427
|
-
console.log(`Applied static certificate for ${domain} from certProvider`);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
catch (err) {
|
|
431
|
-
console.log(`certProvider error for ${domain}: ${err}`);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
console.log('Provisioned certificates for new routes');
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Request a certificate for a specific domain
|
|
441
|
-
*
|
|
442
|
-
* @param domain The domain to request a certificate for
|
|
443
|
-
* @param routeName Optional route name to associate with the certificate
|
|
444
|
-
*/
|
|
445
|
-
async requestCertificate(domain, routeName) {
|
|
446
|
-
// Validate domain format
|
|
447
|
-
if (!this.isValidDomain(domain)) {
|
|
448
|
-
console.log(`Invalid domain format: ${domain}`);
|
|
449
|
-
return false;
|
|
450
|
-
}
|
|
451
|
-
// Use Port80Handler if available
|
|
452
|
-
if (this.port80Handler) {
|
|
453
|
-
try {
|
|
454
|
-
// Check if we already have a certificate
|
|
455
|
-
const cert = this.port80Handler.getCertificate(domain);
|
|
456
|
-
if (cert) {
|
|
457
|
-
console.log(`Certificate already exists for ${domain}, valid until ${cert.expiryDate.toISOString()}`);
|
|
458
|
-
return true;
|
|
459
|
-
}
|
|
460
|
-
// Register domain for certificate issuance
|
|
461
|
-
this.port80Handler.addDomain({
|
|
462
|
-
domain,
|
|
463
|
-
sslRedirect: true,
|
|
464
|
-
acmeMaintenance: true,
|
|
465
|
-
routeReference: routeName ? { routeName } : undefined
|
|
466
|
-
});
|
|
467
|
-
console.log(`Domain ${domain} registered for certificate issuance` + (routeName ? ` for route '${routeName}'` : ''));
|
|
468
|
-
return true;
|
|
469
|
-
}
|
|
470
|
-
catch (err) {
|
|
471
|
-
console.log(`Error registering domain with Port80Handler: ${err}`);
|
|
472
|
-
return false;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
// Fall back to NetworkProxyBridge
|
|
476
|
-
return this.networkProxyBridge.requestCertificate(domain);
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Validates if a domain name is valid for certificate issuance
|
|
480
|
-
*/
|
|
481
|
-
isValidDomain(domain) {
|
|
482
|
-
// Very basic domain validation
|
|
483
|
-
if (!domain || domain.length === 0) {
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
486
|
-
// Check for wildcard domains (they can't get ACME certs)
|
|
487
|
-
if (domain.includes('*')) {
|
|
488
|
-
console.log(`Wildcard domains like "${domain}" are not supported for ACME certificates`);
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
// Check if domain has at least one dot and no invalid characters
|
|
492
|
-
const validDomainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
493
|
-
if (!validDomainRegex.test(domain)) {
|
|
494
|
-
console.log(`Domain "${domain}" has invalid format`);
|
|
495
|
-
return false;
|
|
496
|
-
}
|
|
497
|
-
return true;
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Add a new listening port without changing the route configuration
|
|
501
|
-
*
|
|
502
|
-
* This allows you to add a port listener without updating routes.
|
|
503
|
-
* Useful for preparing to listen on a port before adding routes for it.
|
|
504
|
-
*
|
|
505
|
-
* @param port The port to start listening on
|
|
506
|
-
* @returns Promise that resolves when the port is listening
|
|
507
|
-
*/
|
|
508
|
-
async addListeningPort(port) {
|
|
509
|
-
return this.portManager.addPort(port);
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* Stop listening on a specific port without changing the route configuration
|
|
513
|
-
*
|
|
514
|
-
* This allows you to stop a port listener without updating routes.
|
|
515
|
-
* Useful for temporary maintenance or port changes.
|
|
516
|
-
*
|
|
517
|
-
* @param port The port to stop listening on
|
|
518
|
-
* @returns Promise that resolves when the port is closed
|
|
519
|
-
*/
|
|
520
|
-
async removeListeningPort(port) {
|
|
521
|
-
return this.portManager.removePort(port);
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Get a list of all ports currently being listened on
|
|
525
|
-
*
|
|
526
|
-
* @returns Array of port numbers
|
|
527
|
-
*/
|
|
528
|
-
getListeningPorts() {
|
|
529
|
-
return this.portManager.getListeningPorts();
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Get statistics about current connections
|
|
533
|
-
*/
|
|
534
|
-
getStatistics() {
|
|
535
|
-
const connectionRecords = this.connectionManager.getConnections();
|
|
536
|
-
const terminationStats = this.connectionManager.getTerminationStats();
|
|
537
|
-
let tlsConnections = 0;
|
|
538
|
-
let nonTlsConnections = 0;
|
|
539
|
-
let keepAliveConnections = 0;
|
|
540
|
-
let networkProxyConnections = 0;
|
|
541
|
-
// Analyze active connections
|
|
542
|
-
for (const record of connectionRecords.values()) {
|
|
543
|
-
if (record.isTLS)
|
|
544
|
-
tlsConnections++;
|
|
545
|
-
else
|
|
546
|
-
nonTlsConnections++;
|
|
547
|
-
if (record.hasKeepAlive)
|
|
548
|
-
keepAliveConnections++;
|
|
549
|
-
if (record.usingNetworkProxy)
|
|
550
|
-
networkProxyConnections++;
|
|
551
|
-
}
|
|
552
|
-
return {
|
|
553
|
-
activeConnections: connectionRecords.size,
|
|
554
|
-
tlsConnections,
|
|
555
|
-
nonTlsConnections,
|
|
556
|
-
keepAliveConnections,
|
|
557
|
-
networkProxyConnections,
|
|
558
|
-
terminationStats,
|
|
559
|
-
acmeEnabled: !!this.port80Handler,
|
|
560
|
-
port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null,
|
|
561
|
-
routes: this.routeManager.getListeningPorts().length,
|
|
562
|
-
listeningPorts: this.portManager.getListeningPorts(),
|
|
563
|
-
activePorts: this.portManager.getListeningPorts().length
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* Get a list of eligible domains for ACME certificates
|
|
568
|
-
*/
|
|
569
|
-
getEligibleDomainsForCertificates() {
|
|
570
|
-
const domains = [];
|
|
571
|
-
// Get domains from routes
|
|
572
|
-
const routes = this.settings.routes || [];
|
|
573
|
-
for (const route of routes) {
|
|
574
|
-
if (!route.match.domains)
|
|
575
|
-
continue;
|
|
576
|
-
// Skip routes without TLS termination or auto certificates
|
|
577
|
-
if (route.action.type !== 'forward' ||
|
|
578
|
-
!route.action.tls ||
|
|
579
|
-
route.action.tls.mode === 'passthrough' ||
|
|
580
|
-
route.action.tls.certificate !== 'auto')
|
|
581
|
-
continue;
|
|
582
|
-
const routeDomains = Array.isArray(route.match.domains)
|
|
583
|
-
? route.match.domains
|
|
584
|
-
: [route.match.domains];
|
|
585
|
-
// Skip domains that can't be used with ACME
|
|
586
|
-
const eligibleDomains = routeDomains.filter(domain => !domain.includes('*') && this.isValidDomain(domain));
|
|
587
|
-
domains.push(...eligibleDomains);
|
|
588
|
-
}
|
|
589
|
-
// Legacy mode is no longer supported
|
|
590
|
-
return domains;
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Get NFTables status
|
|
594
|
-
*/
|
|
595
|
-
async getNfTablesStatus() {
|
|
596
|
-
return this.nftablesManager.getStatus();
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Get status of certificates managed by Port80Handler
|
|
600
|
-
*/
|
|
601
|
-
getCertificateStatus() {
|
|
602
|
-
if (!this.port80Handler) {
|
|
603
|
-
return {
|
|
604
|
-
enabled: false,
|
|
605
|
-
message: 'Port80Handler is not enabled'
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
// Get eligible domains
|
|
609
|
-
const eligibleDomains = this.getEligibleDomainsForCertificates();
|
|
610
|
-
const certificateStatus = {};
|
|
611
|
-
// Check each domain
|
|
612
|
-
for (const domain of eligibleDomains) {
|
|
613
|
-
const cert = this.port80Handler.getCertificate(domain);
|
|
614
|
-
if (cert) {
|
|
615
|
-
const now = new Date();
|
|
616
|
-
const expiryDate = cert.expiryDate;
|
|
617
|
-
const daysRemaining = Math.floor((expiryDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000));
|
|
618
|
-
certificateStatus[domain] = {
|
|
619
|
-
status: 'valid',
|
|
620
|
-
expiryDate: expiryDate.toISOString(),
|
|
621
|
-
daysRemaining,
|
|
622
|
-
renewalNeeded: daysRemaining <= (this.settings.acme?.renewThresholdDays ?? 0)
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
else {
|
|
626
|
-
certificateStatus[domain] = {
|
|
627
|
-
status: 'missing',
|
|
628
|
-
message: 'No certificate found'
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
const acme = this.settings.acme;
|
|
633
|
-
return {
|
|
634
|
-
enabled: true,
|
|
635
|
-
port: acme.port,
|
|
636
|
-
useProduction: acme.useProduction,
|
|
637
|
-
autoRenew: acme.autoRenew,
|
|
638
|
-
certificates: certificateStatus
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVnYWN5LXNtYXJ0LXByb3h5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS9sZWdhY3ktc21hcnQtcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxnQ0FBZ0M7QUFDaEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFeEQsd0JBQXdCO0FBQ3hCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saURBQWlELENBQUM7QUFFbEYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFRNUU7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxPQUFPLFVBQVcsU0FBUSxPQUFPLENBQUMsWUFBWTtJQXFCbEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQThCRztJQUNILFlBQVksV0FB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
|