@vladmandic/piproxy
Advanced tools
Comparing version 1.1.24 to 2.0.1
{ | ||
"globals": {}, | ||
"env": { | ||
"browser": true, | ||
"commonjs": true, | ||
"es6": true, | ||
"node": true, | ||
"jquery": true, | ||
"es2020": true | ||
"commonjs": true, | ||
"node": true, | ||
"es2022": true | ||
}, | ||
"parserOptions": { "ecmaVersion": "latest" }, | ||
"plugins": [ "html" ], | ||
"parser": "@typescript-eslint/parser", | ||
"parserOptions": { "ecmaVersion": 2022 }, | ||
"plugins": [ | ||
"@typescript-eslint", | ||
"import", | ||
"json" | ||
], | ||
"extends": [ | ||
"airbnb-base", | ||
"eslint:recommended", | ||
"plugin:import/errors", | ||
"plugin:import/warnings", | ||
"plugin:node/recommended", | ||
"plugin:promise/recommended", | ||
"plugin:json/recommended", | ||
"airbnb-base" | ||
"plugin:@typescript-eslint/eslint-recommended", | ||
"plugin:@typescript-eslint/recommended", | ||
"plugin:json/recommended-with-comments", | ||
"plugin:import/typescript" | ||
], | ||
"ignorePatterns": [], | ||
"rules": { | ||
"max-len": [1, 270, 3], | ||
"camelcase": "off", | ||
"guard-for-in": "off", | ||
"import/extensions": "off", | ||
"no-await-in-loop": "off", | ||
"no-bitwise": "off", | ||
"max-len": [1, 275, 3], | ||
"@typescript-eslint/ban-ts-comment":"off", | ||
"dot-notation":"off", | ||
"import/extensions":"off", | ||
"import/prefer-default-export":"off", | ||
"import/no-extraneous-dependencies":"off", | ||
"lines-between-class-members":"off", | ||
"no-await-in-loop":"off", | ||
"no-bitwise":"off", | ||
"no-mixed-operators":"off", | ||
"no-plusplus":"off", | ||
"no-case-declarations":"off", | ||
"no-continue": "off", | ||
"no-loop-func": "off", | ||
"no-mixed-operators": "off", | ||
"no-param-reassign":"off", | ||
"no-plusplus": "off", | ||
"no-restricted-globals": "off", | ||
"no-restricted-syntax": "off", | ||
"no-underscore-dangle": "off", | ||
"node/no-unsupported-features/es-syntax": "off", | ||
"node/shebang": "off", | ||
"object-curly-newline": "off", | ||
"prefer-destructuring": "off", | ||
"promise/always-return": "off", | ||
"promise/catch-or-return": "off", | ||
"promise/no-nesting": "off", | ||
"no-restricted-syntax":"off", | ||
"no-regex-spaces":"off", | ||
"dot-notation": "off", | ||
"no-unneeded-ternary": "off", | ||
"promise/no-callback-in-promise": "off" | ||
"object-curly-newline":"off", | ||
"prefer-template":"off", | ||
"radix":"off" | ||
} | ||
} | ||
} |
@@ -16,11 +16,4 @@ --- | ||
**Environment | ||
**Environment** | ||
- Module version? | ||
- Built-in demo or custom code? | ||
- Type of module used (e.g. `js`, `esm`, `esm-nobundle`)? | ||
- Browser or NodeJS and version (e.g. NodeJS 14.15 or Chrome 89)? | ||
- OS and Hardware platform (e.g. Windows 10, Ubuntu Linux on x64, Android 10)? | ||
- Packager (if any) (e.g, webpack, rollup, parcel, esbuild, etc.)? | ||
**Additional** | ||
@@ -27,0 +20,0 @@ |
@@ -1,18 +0,39 @@ | ||
# PiGallery Change Log | ||
# @vladmandic/piproxy | ||
### **HEAD -> master, origin/master, origin/HEAD** 2022/08/11 mandic00@live.com | ||
Version: **2.0.0** | ||
Description: **Reverse HTTP/HTTPS/HTTP2 Proxy in NodeJS with SSL Certificate Management, Compression, Security Enforcement and Rate Limiting** | ||
Author: **Vladimir Mandic <mandic00@live.com>** | ||
License: **MIT** | ||
Repository: **<https://github.com/vladmandic/piproxy>** | ||
## Changelog | ||
### **HEAD -> master** 2022/08/14 mandic00@live.com | ||
### **1.1.24** 2022/08/11 mandic00@live.com | ||
- fix loading of service workers | ||
### **1.1.23** 2022/05/25 mandic00@live.com | ||
### **1.1.22** 2022/03/20 mandic00@live.com | ||
### **1.1.21** 2021/12/14 mandic00@live.com | ||
### **1.1.20** 2021/10/02 mandic00@live.com | ||
### **1.1.19** 2021/07/29 mandic00@live.com | ||
### **tag: 1.1.8** 2021/04/22 mandic00@live.com | ||
### **release: 1.1.8** 2021/04/22 mandic00@live.com | ||
### **1.1.18** 2021/04/21 mandic00@live.com | ||
- fix frame-ancesor for iframes | ||
@@ -23,20 +44,27 @@ - reimplement header handling | ||
### **1.1.16** 2021/03/18 mandic00@live.com | ||
### **1.1.15** 2021/03/13 mandic00@live.com | ||
### **1.1.14** 2021/02/20 mandic00@live.com | ||
### **tag: v1.1.13** 2021/02/19 mandic00@live.com | ||
### **1.1.13** 2021/02/19 mandic00@live.com | ||
### **1.1.11** 2021/01/29 mandic00@live.com | ||
### **1.1.10** 2021/01/22 mandic00@live.com | ||
### **1.1.9** 2021/01/22 mandic00@live.com | ||
- strict linting | ||
### **1.1.8** 2021/01/03 mandic00@live.com | ||
- merge branch 'master' of https://github.com/vladmandic/piproxy | ||
@@ -47,2 +75,3 @@ - merge pull request #3 from vladmandic/dependabot/npm_and_yarn/ini-1.3.8 | ||
### **1.1.7** 2020/12/12 mandic00@live.com | ||
- port update | ||
@@ -53,15 +82,23 @@ - package update | ||
### **1.1.5** 2020/11/25 mandic00@live.com | ||
### **tag: v2** 2020/10/29 mandic00@live.com | ||
### **2** 2020/10/29 mandic00@live.com | ||
### **1.1.4** 2020/10/28 mandic00@live.com | ||
### **1.1.3** 2020/09/26 mandic00@live.com | ||
### **1.1.2** 2020/09/16 cyan00@gmail.com | ||
### **1.1.1** 2020/09/16 cyan00@gmail.com | ||
### **1.0.24** 2020/09/16 cyan00@gmail.com | ||
- improved error handler | ||
@@ -71,9 +108,13 @@ | ||
### **1.0.22** 2020/09/11 cyan00@gmail.com | ||
- autorestart on ssl cert update | ||
### **1.0.21** 2020/09/05 cyan00@gmail.com | ||
- fix firefox compression compatibility issue | ||
### **1.0.20** 2020/09/04 cyan00@gmail.com | ||
- add gzip as alternative | ||
@@ -83,3 +124,5 @@ | ||
### **1.0.18** 2020/08/28 cyan00@gmail.com | ||
- excluded js map files | ||
@@ -89,2 +132,3 @@ - monitoring and stats improvements | ||
### **1.0.17** 2020/08/22 cyan00@gmail.com | ||
- reduced dependencies | ||
@@ -94,2 +138,3 @@ - tweaks | ||
### **1.0.16** 2020/08/22 cyan00@gmail.com | ||
- econding fix | ||
@@ -99,2 +144,3 @@ - compression update | ||
### **1.0.15** 2020/08/19 cyan00@gmail.com | ||
- added geoip db to git lfs | ||
@@ -104,2 +150,3 @@ - added | ||
### **1.0.14** 2020/08/19 cyan00@gmail.com | ||
- automatic server monitoring | ||
@@ -109,2 +156,3 @@ - added predefined responses | ||
### **1.0.13** 2020/08/19 cyan00@gmail.com | ||
- improved logging | ||
@@ -114,3 +162,5 @@ | ||
### **1.0.11** 2020/08/14 cyan00@gmail.com | ||
- url query | ||
@@ -121,5 +171,7 @@ - enhanced stats | ||
### **1.0.10** 2020/08/13 cyan00@gmail.com | ||
- initial work on stats page | ||
### **1.0.9** 2020/08/11 cyan00@gmail.com | ||
- fix statuscode | ||
@@ -129,11 +181,15 @@ - ip resolving fix | ||
### **1.0.8** 2020/08/10 cyan00@gmail.com | ||
- implemented brotli compression | ||
### **1.0.7** 2020/08/10 cyan00@gmail.com | ||
- priviledge drop | ||
### **1.0.6** 2020/08/08 cyan00@gmail.com | ||
- simplified dependencies | ||
### **1.0.5** 2020/08/06 cyan00@gmail.com | ||
- improved configuration options | ||
@@ -143,6 +199,9 @@ | ||
### **1.0.3** 2020/08/02 cyan00@gmail.com | ||
- custom error handler | ||
### **1.0.2** 2020/08/02 cyan00@gmail.com | ||
- added helmet protection and rate limiter | ||
@@ -152,2 +211,3 @@ - rewrite using native methods | ||
### **1.0.1** 2020/08/01 cyan00@gmail.com | ||
- added secure server redirect | ||
@@ -157,5 +217,8 @@ | ||
### **tag: 1.0.0** 2020/07/19 cyan00@gmail.com | ||
### **release: 1.0.0** 2020/07/19 cyan00@gmail.com | ||
### **0.0.5** 2020/07/19 cyan00@gmail.com | ||
- http2 logging | ||
@@ -165,3 +228,5 @@ | ||
### **0.0.3** 2020/06/28 cyan00@gmail.com | ||
- noip refresh bugfix | ||
@@ -172,3 +237,4 @@ - deleted logs | ||
### **0.0.2** 2020/06/27 cyan00@gmail.com | ||
- readme and systemd file update | ||
- initial commit |
{ | ||
"name": "@vladmandic/piproxy", | ||
"version": "1.1.24", | ||
"description": "PiProxy: Reverse Proxy in NodeJS for HTTP/HTTPS/HTTP2 with SSL Certificate Management, Compression, Security Enforcement and Rate Limiting", | ||
"main": "server/piproxy.js", | ||
"version": "2.0.1", | ||
"description": "Reverse HTTP/HTTPS/HTTP2 Proxy in NodeJS with SSL Certificate Management, Compression, Security Enforcement and Rate Limiting", | ||
"main": "dist/piproxy.js", | ||
"sideEffects": false, | ||
"scripts": { | ||
"start": "node --unhandled-rejections=strict server/piproxy.js", | ||
"setup": "node ./setup.js", | ||
"lint": "eslint *.json *.js server/*.js" | ||
"build": "build --profile production", | ||
"start": "node --unhandled-rejections=throw dist/piproxy.js", | ||
"dev": "build --profile production && node --trace-uncaught --trace-warnings --unhandled-rejections=strict --enable-source-maps dist/piproxy.js", | ||
"lint": "eslint *.json src/*" | ||
}, | ||
@@ -37,8 +38,6 @@ "repository": { | ||
"dependencies": { | ||
"@vladmandic/piacme": "^0.1.30", | ||
"@vladmandic/pilogger": "^0.4.6", | ||
"@vladmandic/piacme": "^1.0.2", | ||
"connect": "^3.7.0", | ||
"helmet": "^5.1.1", | ||
"maxmind": "^4.3.6", | ||
"nedb-promises": "^6.1.0", | ||
"simple-git": "^3.12.0", | ||
@@ -48,3 +47,9 @@ "superagent": "^8.0.0" | ||
"devDependencies": { | ||
"eslint": "^8.21.0", | ||
"@types/node": "^18.7.3", | ||
"@typescript-eslint/eslint-plugin": "^5.33.0", | ||
"@typescript-eslint/parser": "^5.33.0", | ||
"@vladmandic/build": "^0.7.9", | ||
"@vladmandic/pilogger": "^0.4.6", | ||
"esbuild": "^0.15.3", | ||
"eslint": "^8.22.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
@@ -55,4 +60,6 @@ "eslint-plugin-html": "^7.1.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^6.0.0" | ||
"eslint-plugin-promise": "^6.0.0", | ||
"tslib": "^2.4.0", | ||
"typescript": "4.7.4" | ||
} | ||
} |
363
README.md
@@ -1,3 +0,13 @@ | ||
# PiProxy: Reverse Proxy in NodeJS for HTTP/HTTPS/HTTP2 with Automatic SSL Management, Compression, Security Enforcement and Rate Limiting | ||
# PiProxy | ||
*Reverse Proxy in NodeJS for HTTP/HTTPS/HTTP2 with Automatic SSL Management, Compression, Security Enforcement and Rate Limiting* | ||
When you run a server app that runs as web server, you want a way to expose it using user-friendly URL | ||
And typically this is done using and configuring a commerical grade server such as [nginx](https://nginx.org/en/) that will perform reverse proxy functions from user-friendly URL to your local server | ||
But what if you want to do it all in `NodeJS`? | ||
And have automatic handling of dynamic DNS and SSL certificates? | ||
<br> | ||
## Features | ||
@@ -16,234 +26,119 @@ | ||
- Agent analysis on access | ||
- Text file and DB logging | ||
- Performance and size measurements | ||
- Built-in statistcs | ||
- Full logging support | ||
## Run | ||
<br> | ||
Simply install and run: | ||
## Install & Run | ||
- Make sure you have [NodeJS](https://nodejs.org/en/) already installed | ||
- Clone repository | ||
`git clone https://github.com/vladmandic/piproxy` | ||
or download and unpack from <https://github.com/vladmandic/piproxy/releases/> | ||
- Install using | ||
`./setup.js` | ||
This will install all dependencies as needed | ||
- Run using: | ||
`npm start` or | ||
`node server/piproxy` or use | ||
`piproxy.service` as a template (notes are within service file) to create a Linux service | ||
(see section on security to see how to run as non-root) | ||
### Prerequisites | ||
1. Install [NodeJS](https://nodejs.org/en/) | ||
2. Set [NodeJS](https://nodejs.org/en/) permissions | ||
See section [Permissions](###Permissions) for options | ||
3. Choose how you want to handle SSL certificates | ||
See section [SSL Options](###SSL-Options) for options | ||
4. Set your **router** to redirect all HTTPS traffic to your proxy server | ||
This will allow secure access from internet | ||
Alternatively, run without external access | ||
Note that external access is required to require valid signed SSL certificate | ||
5. If you want to perform optional location lookups based on IP, | ||
download [MaxMind](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en) city and ASN databases | ||
### Install & Run | ||
1. Clone latest version of `piproxy` | ||
> git clone --depth 1 https://github.com/vladmandic/piproxy` | ||
2. Create configuration | ||
Rename `config.json.sample` to `config.json` and modify it as needed | ||
See section [Configuration](##Configuration) for details | ||
3. Start `piproxy`: | ||
> `npm start` | ||
or use `piproxy.service` as a template (notes are within service file) to create a Linux `systemd` service | ||
<br> | ||
## Configuration | ||
Entire configuration is inside `server/piproxy.js` config object and all values are *optional* | ||
Example of minimum configuration from `config.json.sample`: | ||
### Example configuration | ||
```js | ||
global.config = { | ||
logFile: 'piproxy.log', | ||
// if present, piproxy will attempt regular dynamic dns updates for specified domains on no-ip service | ||
noip: { | ||
host: ['example1.ddns.net', 'example2.ddns.net', 'example3.ddns.net'], | ||
user: 'user', | ||
password: 'password', | ||
}, | ||
// if present, piproxy will attempt automatic registration on letsencrypt to obtain ssl certificate | ||
// once certificate is obtain, it will be monitored for validity and auto-renewed as needed | ||
// only fields needed are maintainer/subscriber and list of domains for which to obtain certificate | ||
acme: { | ||
application: 'piproxy/1.0.0', | ||
domains: ['example1.ddns.net', 'example2.ddns.net', 'example3.ddns.net'], | ||
maintainer: 'user@example.com', | ||
subscriber: 'user@example.com', | ||
accountFile: './cert/account.json', | ||
accountKeyFile: './cert/account.pem', | ||
ServerKeyFile: './cert//private.pem', | ||
fullChain: './cert/fullchain.pem', | ||
}, | ||
// alternatively, if you don't want to use acme module, you can specify your own ssl keys here | ||
ssl: { | ||
Key: 'file-with-server-private-key', | ||
Crt: 'file-with-server-certificate', | ||
}, | ||
// piproxy runs as secure http2 server while target server can be anything | ||
http2: { | ||
allowHTTP1: true, | ||
port: 443, | ||
secureOptions: crypto.constants.SSL_OP_NO_TLSv1 | crypto.constants.SSL_OP_NO_TLSv1_1, | ||
}, | ||
// automatically redirect http requests to https | ||
redirectHTTP: true, | ||
// this is the main redirect list for reverse proxy | ||
redirects: [ | ||
{ url: 'example1.ddns.net', target: 'localhost', port: '8000' }, | ||
{ url: 'example2.ddns.net', target: 'localhost', port: '8001' }, | ||
{ url: 'example3.ddns.net', target: 'localhost', port: '8002' }, | ||
{ default: true, target: 'localhost', port: '8000' }, | ||
```json | ||
{ | ||
// main section that controls all reverse proxy functions | ||
"redirects": [ | ||
// for any request matching `weather.ddns.net` fetch data from `locahost:10000` | ||
{ "url": "weather.ddns.net", "target": "localhost", "port": "10000" }, | ||
{ "url": "clock.ddns.net", "target": "localhost", "port": "10010" }, | ||
{ "url": "profile.ddns.net", "target": "localhost", "port": "10020" }, | ||
// for any request that does not match any rule fetch data from `locahost:10000` | ||
{ "default": true, "target": "localhost", "port": "10000" } | ||
], | ||
// automatic status monitoring of both destination urls and targets listed in redirects | ||
monitor: true, | ||
// if present, piproxy will throttle requests | ||
limiter: { | ||
interval: 10, | ||
tokens: 500, | ||
// optional: update dynamic ip for a listed hosts using provided username and password at no-ip service | ||
"noip": { | ||
"host": [ "weather.ddns.net", "clock.ddns.net", "profile.ddns.net" ], | ||
"user": "me@example.com", | ||
"password": "password" | ||
}, | ||
// if present, piproxy will compress all responses with specific compression level before sending them out | ||
// exception is if client does not understand enhanced compression or output has already been compressed | ||
// supported are gzip and brotli with brotli as default | ||
// set to 0 to disable compression | ||
compress: 5, | ||
// log to database in addition to a log file | ||
db: 'piproxy.db', | ||
// use geoip reverse lookups to locate requests | ||
// databases can be obtained for free from maxmind at <https://dev.maxmind.com/geoip/geoip2/geolite2/> | ||
geoIP: { | ||
city: './geoip/GeoLite2-City.mmdb', | ||
asn: './geoip/GeoLite2-ASN.mmdb', | ||
// optional: automatically handle ssl certificates for listsed domains using let's encrypt service | ||
"acme": { | ||
"domains": [ "weather.ddns.net", "clock.ddns.net", "profile.ddns.net" ], | ||
"maintainer": "me@example.com", | ||
"subscriber": "me@example.com" | ||
}, | ||
// if present, piproxy will use helmet module for additional security | ||
helmet: { | ||
frameguard: { action: 'deny' }, | ||
xssFilter: false, | ||
dnsPrefetchControl: { allow: 'true' }, | ||
noSniff: false, | ||
hsts: { maxAge: 15552000, preload: true }, | ||
referrerPolicy: { policy: 'no-referrer' }, | ||
expectCt: { enforce: true }, | ||
contentSecurityPolicy: { | ||
// modify csp policies as needed to match your requirements | ||
directives: { | ||
'default-src': ["'self'"], | ||
'img-src': ["'self'", 'data:', 'http:', 'https:'], | ||
'script-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'"], | ||
'style-src': ["'self'", 'https:', "'unsafe-inline'"], | ||
'connect-src': ["'self'", 'http:', 'https:', 'data:'], | ||
'upgrade-insecure-requests': [], | ||
}, | ||
}, | ||
}, | ||
// if present, piproxy will reply with default answers to standard url requests | ||
// simply remove if you want to manage your own as then piproxy will perform passthrough requests | ||
'security.txt': 'Contact: mailto:user@example.com\nPreferred-Languages: en\n', | ||
'humans.txt': '/* TEAM */\nChef: Unknown chef\nContact: user@example.com\nGitHub: https://github.com/vladmandic\n', | ||
'robots.txt': 'User-agent: *\nDisallow: /private\nCrawl-delay: 10\n', | ||
'git.head': 'ref: refs/heads/master\n', | ||
'sitemap.xml': '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n<url>\n<loc>URL</loc>\n</url>\n</urlset>', | ||
}; | ||
// optional: provide predefined http responses on some well known static paths | ||
"answers": { | ||
"security.txt": "Contact: mailto:me@example.com\nPreferred-Languages: en\n" | ||
} | ||
} | ||
``` | ||
### Permissions | ||
Default locations (can be changed in advanced configuration): | ||
- Certificates are stored in `/cert` | ||
- Logs are stored in `/logs` | ||
- GeoIP databases are stored in `/geoip` | ||
To allow the server to listen on privledged ports (TCP ports below 1024), you need to either: | ||
Full configuration details can be seen at [https://github.com/vladmandic/piproxy/tree/master/src/config.ts] | ||
1. Configure your system so node process can bind to priviledged ports without running as root: | ||
(you only need to do this once) | ||
<br> | ||
```shell | ||
sudo setcap 'cap_net_bind_service=+ep' `which node` | ||
``` | ||
## Notes | ||
### SSL Options | ||
2. Run node as root with sudo: | ||
- Provide your own private key and server certificate | ||
```shell | ||
sudo node server/piproxy.js | ||
``` | ||
- Generate self-signed private key and server certificate | ||
In that case, PiProxy will automatically try to drop priviledges as soon as server is started: | ||
Note: Do not login as root and then run node - it is highly insecure! | ||
> openssl req -x509 -newkey rsa:4096 -nodes -days 365 \ | ||
-keyout https.key -out https.crt \ | ||
-subj "/C=US/ST=Florida/L=Miami/O=@vladmandic" | ||
```log | ||
2020-08-10 15:02:19 STATE: Reducing runtime priviledges | ||
2020-08-10 15:02:19 STATE: Running as UID:1000 | ||
``` | ||
- Allow `piproxy` to automatically get signed certificate from [Let's Encypt](https://letsencrypt.org/) | ||
In this case, `piproxy` will automatically handle certificate renewals | ||
3. Run node on a non-priviledged port and forward a desired priviledged port to a non-priviledged one using firewall NAT configuration. For example, to route TCP port 443 (https) to port 8000: | ||
### Permissions | ||
```shell | ||
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000 | ||
or | ||
sudo ipfw add 100 fwd 127.0.0.1,8000 tcp from any to any 80 in | ||
``` | ||
To allow the server to listen on privledged ports (TCP ports below 1024), you need to either: | ||
### Advanced usage | ||
- Configure your system so node process can bind to priviledged ports without running as root: | ||
(you only need to do this once) | ||
> sudo setcap 'cap_net_bind_service=+ep' `which node` | ||
For custom error handling, see `server/proxy.js:findTarget()` function which currently implements custom handler for error 404 (HTTP Not Found) by returning content of `server/error.js:get404()` instead of forwarding error as-is from a proxied server. | ||
- Run node as root with sudo: | ||
> sudo node server/proxy.js | ||
In that case, proxy will automatically try to drop priviledges as soon as server is started | ||
## Example log | ||
- Run node on a non-priviledged port and | ||
forward a desired priviledged port to a non-priviledged one using firewall NAT configuration | ||
For example, to route TCP port 443 (https) to port 8000: | ||
Sample PiProxy startup log: | ||
> sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8000 | ||
```log | ||
2020-08-19 12:25:10 INFO: @vladmandic/piproxy version 1.0.13 | ||
2020-08-19 12:25:10 INFO: User: vlado Platform: linux Arch: x64 Node: v14.8.0 | ||
2020-08-19 12:25:10 STATE: Application log: /home/vlado/dev/piproxy/piproxy.log | ||
2020-08-19 12:25:10 STATE: Change log updated: /home/vlado/dev/piproxy/CHANGELOG.md | ||
2020-08-19 12:25:10 INFO: ACME certificate: check: ./cert/fullchain.pem | ||
2020-08-19 12:25:10 INFO: SSL account: mailto:mandic00@live.com created: 2020-04-23 21:55:15 | ||
2020-08-19 12:25:10 INFO: SSL keys server:RSA account:EC | ||
2020-08-19 12:25:10 INFO: SSL certificate subject:pidash.ddns.net issuer:Let's Encrypt Authority X3 | ||
2020-08-19 12:25:10 STATE: SSL certificate expires in 34.3 days, skipping renewal | ||
2020-08-19 12:25:10 STATE: GeoIP databases loaded | ||
2020-08-19 12:25:10 INFO: Log database: /home/vlado/dev/piproxy/piproxy.db | ||
2020-08-19 12:25:10 INFO: Enabling Helmet protection | ||
2020-08-19 12:25:10 INFO: Enabling rate limiter: { interval: 10, tokens: 500 } | ||
2020-08-19 12:25:10 INFO: Rule: { url: 'pidash.ddns.net', target: 'localhost', port: '10000' } | ||
2020-08-19 12:25:10 INFO: Rule: { url: 'pigallery.ddns.net', target: 'localhost', port: '10010' } | ||
2020-08-19 12:25:10 INFO: Rule: { url: 'pimiami.ddns.net', target: 'localhost', port: '10020' } | ||
2020-08-19 12:25:10 INFO: Rule: { default: true, target: 'localhost', port: '10010' } | ||
2020-08-19 12:25:10 INFO: Activating reverse proxy | ||
2020-08-19 12:25:10 STATE: Proxy listening: { address: '::', family: 'IPv6', port: 443 } | ||
2020-08-19 12:25:17 STATE: Monitoring { url: 'pidash.ddns.net', target: 'localhost', port: '10000' } URL: { lookup: true, connect: true, ready: true } Target: { lookup: true, connect: true, ready: true } | ||
2020-08-19 12:25:17 STATE: Monitoring { url: 'pigallery.ddns.net', target: 'localhost', port: '10010' } URL: { lookup: true, connect: true, ready: true } Target: { lookup: true, connect: true, ready: true } | ||
2020-08-19 12:25:17 STATE: Monitoring { url: 'pimiami.ddns.net', target: 'localhost', port: '10020' } URL: { lookup: true, connect: true, ready: true } Target: { lookup: true, connect: true, ready: true } | ||
2020-08-19 12:25:17 STATE: Monitoring { default: true, target: 'localhost', port: '10010' } URL: { lookup: true, connect: true, ready: true } Target: { lookup: true, connect: true, ready: true } | ||
2020-08-19 12:25:17 STATE: NoIP { hostname: 'pimiami.ddns.net', status: 200, text: 'nochg 159.250.182.243' } | ||
2020-08-19 12:25:17 STATE: NoIP { hostname: 'pigallery.ddns.net', status: 200, text: 'nochg 159.250.182.243' } | ||
2020-08-19 12:25:17 STATE: NoIP { hostname: 'pidash.ddns.net', status: 200, text: 'nochg 159.250.182.243' }``` | ||
``` | ||
or | ||
Note that in addition to request analysis, note that piproxy also measures duration of the response from target server as well as the length of the response. | ||
> sudo ipfw add 100 fwd 127.0.0.1,8000 tcp from any to any 80 in | ||
Sample actual reverse proxy log: | ||
```log | ||
2020-08-19 11:33:15 DATA: GET/h2 Code: 200 https://pimiami.ddns.net/ From:::ffff:172.58.14.224 Length: 3758 Agent:AppleWebKit/537.36 Chrome/77.0.3865.116 Mobile Safari/537.36 EdgA/45.07.4.5054 Device:Linux; Android 10; SM-G975U Geo:'NA/US/Miami' ASN:'T-Mobile USA, Inc.' Loc:25.8119,-80.2318 | ||
2020-08-19 11:33:16 DATA: GET/h2 Code: 200 https://pimiami.ddns.net/piclock.js From:::ffff:172.58.14.224 Length: 6576 Agent:AppleWebKit/537.36 Chrome/77.0.3865.116 Mobile Safari/537.36 EdgA/45.07.4.5054 Device:Linux; Android 10; SM-G975U Geo:'NA/US/Miami' ASN:'T-Mobile USA, Inc.' Loc:25.8119,-80.2318 | ||
2020-08-19 11:33:17 DATA: GET/h2 Code: 200 https://pimiami.ddns.net/favicon.png From:::ffff:172.58.14.224 Length: 34831 Agent:AppleWebKit/537.36 Chrome/77.0.3865.116 Mobile Safari/537.36 EdgA/45.07.4.5054 Device:Linux; Android 10; SM-G975U Geo:'NA/US/Miami' ASN:'T-Mobile USA, Inc.' Loc:25.8119,-80.2318 | ||
``` | ||
### Compression | ||
## Example database record | ||
```js | ||
{ | ||
timestamp: 2020-08-14T11:36:49.503Z, | ||
method: 'GET', | ||
protocol: 'h2', | ||
status: 200, | ||
scheme: 'https', | ||
host: 'pimiami.ddns.net', | ||
url: '/', | ||
ip: '::ffff:172.58.173.63', | ||
length: '3794', | ||
agent: 'AppleWebKit/537.36 Chrome/77.0.3865.116 Mobile Safari/537.36 EdgA/45.07.4.5054', | ||
device: 'Linux; Android 10; SM-G975U', | ||
country: 'US', | ||
continent: 'NA', | ||
city: 'Orlando', | ||
asn: 'T-Mobile USA, Inc.', | ||
lat: 28.53, | ||
lon: -81.4057, | ||
accuracy: 500, | ||
etag: 'W/"1a-0BqrfQKkcPxt5MD1uQ+QrVjOnGo"', | ||
mime: 'text/html', | ||
duration: 8 | ||
} | ||
``` | ||
## Compression | ||
PiProxy uses Brotli algorithm with a configurable level of compression. | ||
proxy uses Brotli algorithm with a configurable level of compression. | ||
Example of compression efficiency on pure html: | ||
@@ -257,3 +152,3 @@ | ||
## GeoIP | ||
### GeoIP | ||
@@ -272,14 +167,58 @@ GeoIP databases are not included in the package and should be provided by user. | ||
## Statistics | ||
## Example Log | ||
You can access PiProxy statistics on any domain it serves under `/piproxy`. | ||
Example: <https://test.example.com/piproxy> | ||
### Startup | ||
### Advanced queries | ||
```js | ||
2022-08-14 11:01:13 INFO: configuration { file: 'config.json' } | ||
2022-08-14 11:01:13 INFO: { application: '@vladmandic/piproxy', version: '2.0.0' } | ||
2022-08-14 11:01:13 INFO: { user: 'vlado', platform: 'linux', arch: 'x64', node: 'v18.7.0' } | ||
2022-08-14 11:01:13 STATE: { log: '/home/vlado/dev/piproxy/logs/proxy.log', access: '/home/vlado/dev/piproxy', client: '/home/vlado/dev/piproxy' } | ||
2022-08-14 11:01:13 INFO: ssl { key: '../cert/private.pem', crt: '../cert/fullchain.pem' } | ||
2022-08-14 11:01:13 INFO: ssl account { contact: 'mailto:mandic00@live.com', status: 'valid', type: 'EC', crv: 'P-256' } | ||
2022-08-14 11:01:13 INFO: ssl server { subject: 'pidash.ddns.net', issuer: "C=US, O=Let's Encrypt, CN=R3", algorithm: 'sha256WithRSAEncryption', from: 2022-07-12T12:09:02.000Z, until: 2022-10-10T12:09:01.000Z, type: 'RSA', use: 'sig' } | ||
2022-08-14 11:01:13 INFO: ssl certificate { check: './cert/fullchain.pem' } | ||
2022-08-14 11:01:13 STATE: ssl certificate validity { days: 57, renew: 'skip' } | ||
2022-08-14 11:01:13 STATE: geoip { city: './geoip/GeoLite2-City.mmdb', asn: './geoip/GeoLite2-ASN.mmdb' } | ||
2022-08-14 11:01:13 INFO: helmet { frameguard: false, xssFilter: false, dnsPrefetchControl: { allow: true }, noSniff: false, hsts: { maxAge: 15552000, preload: true }, referrerPolicy: { policy: 'no-referrer' }, expectCt: { enforce: true }, contentSecurityPolicy: { directives: { count: [ '10' ] } } } | ||
2022-08-14 11:01:13 INFO: limiter { interval: 10, tokens: 500 } | ||
2022-08-14 11:01:13 INFO: compression { brotli: 5 } | ||
2022-08-14 11:01:13 INFO: proxy { url: 'pimiami.ddns.net', target: 'localhost', port: '10060' } | ||
2022-08-14 11:01:13 INFO: proxy { url: 'weather.local', target: 'localhost', port: '10060' } | ||
2022-08-14 11:01:13 INFO: proxy { url: 'stocks.local', target: 'localhost', port: '10040' } | ||
2022-08-14 11:01:13 INFO: proxy { url: 'pi.hole', target: 'localhost', port: '10050' } | ||
2022-08-14 11:01:13 INFO: proxy { default: true, target: 'localhost', port: '10020' } | ||
2022-08-14 11:01:13 INFO: static { paths: [ 'security.txt', 'humans.txt', 'robots.txt', 'git.head', 'sitemap.xml', 'version' ] } | ||
2022-08-14 11:01:13 STATE: server { status: 'listening', address: '::', family: 'IPv6', port: 443 } | ||
2022-08-14 11:01:13 STATE: server { user: { uid: 1000, gid: 1000, username: 'vlado', homedir: '/home/vlado', shell: '/bin/bash' } } | ||
2022-08-14 11:01:13 STATE: noip { hostname: 'pimiami.ddns.net', status: 200, text: 'nochg 159.250.178.205' } | ||
2022-08-14 11:01:15 STATE: monitor { server: { url: 'pimiami.ddns.net', target: 'localhost', port: '10060' }, url: { lookup: false, connect: false, error: '', ready: false, data: false }, target: { lookup: false, connect: false, error: '', ready: false, data: false } } | ||
2022-08-14 11:01:16 STATE: monitor { server: { url: 'weather.local', target: 'localhost', port: '10060' }, url: { lookup: false, connect: false, error: '', ready: false, data: false }, target: { lookup: false, connect: false, error: '', ready: false, data: false } } | ||
2022-08-14 11:01:16 STATE: monitor { server: { url: 'stocks.local', target: 'localhost', port: '10040' }, url: { lookup: false, connect: false, error: '', ready: false, data: false }, target: { lookup: false, connect: false, error: '', ready: false, data: false } } | ||
2022-08-14 11:01:16 STATE: monitor { server: { url: 'pi.hole', target: 'localhost', port: '10050' }, url: { lookup: false, connect: false, error: '', ready: false, data: false }, target: { lookup: false, connect: false, error: '', ready: false, data: false } } | ||
2022-08-14 11:01:17 STATE: monitor { server: { default: true, target: 'localhost', port: '10020' }, url: { lookup: false, connect: false, error: '', ready: false, data: false }, target: { lookup: false, connect: false, error: '', ready: false, data: false } } | ||
2022-08-14 11:01:18 STATE: server { status: 'active', connections: 0, error: null } | ||
``` | ||
You can pass query params to statistics module directly using URL params (any database field can be queried) | ||
Example: <https://example1.ddns.com/piproxy?'"host":"example1.ddns.net"'> | ||
### Client Requests | ||
## Change log | ||
```js | ||
2022-08-14 11:05:33 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/', device: 'Windows NT 10.0; Win64; x64', mime: 'text/html; charset=utf-8', duration: 550 } | ||
2022-08-14 11:05:33 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/index.css', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/index.css', device: 'Windows NT 10.0; Win64; x64', mime: 'text/css; charset=utf-8', duration: 11 } | ||
2022-08-14 11:05:33 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/assets/leaflet.css', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/assets/leaflet.css', device: 'Windows NT 10.0; Win64; x64', mime: 'text/css; charset=utf-8', duration: 12 } | ||
2022-08-14 11:05:34 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/dist/index.js', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/dist/index.js', device: 'Windows NT 10.0; Win64; x64', mime: 'text/javascript; charset=utf-8', duration: 35 } | ||
2022-08-14 11:05:34 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/favicon.ico', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/favicon.ico', device: 'Windows NT 10.0; Win64; x64', mime: 'image/x-icon', duration: 9 } | ||
2022-08-14 11:05:34 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/dist/pwa-serviceworker.js', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/dist/pwa-serviceworker.js', device: 'Windows NT 10.0; Win64; x64', mime: 'text/javascript; charset=utf-8', duration: 11 } | ||
2022-08-14 11:05:34 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/weather.webmanifest', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/weather.webmanifest', device: 'Windows NT 10.0; Win64; x64', mime: 'application/manifest+json', duration: 5 } | ||
2022-08-14 11:05:34 DATA: { method: 'GET', protocol: 'h2', status: 200, scheme: 'https', host: 'pimiami.ddns.net', url: '/assets/icons/dash-256.png', ip: '::ffff:192.168.0.201', agent: [ 'AppleWebKit/537.36', 'Chrome/104.0.5112.81', 'Safari/537.36', 'Edg/104.0.1293.54' ], client: 'https://pimiami.ddns.net/assets/icons/dash-256.png', device: 'Windows NT 10.0; Win64; x64', mime: 'image/png', duration: 6 } | ||
``` | ||
<https://github.com/vladmandic/piproxy/CHANGELOG.md> | ||
## Links | ||
- [License](https://github.com/vladmandic/proxy/LICENSE) | ||
- [Contributing Guidelines](https://github.com/vladmandic/proxy/CONTRIBUTING) | ||
- [Security Policy](https://github.com/vladmandic/proxy/SECURITY) | ||
- [Code of Conduct](https://github.com/vladmandic/proxy/CODE_OF_CONDUCT) | ||
- [Change Log](https://github.com/vladmandic/proxy/CHANGELOG.md) | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
110961
6
2216
3
8
15
222
+ Added@vladmandic/piacme@1.0.3(transitive)
+ Addedcert2json@1.0.13(transitive)
- Removed@vladmandic/pilogger@^0.4.6
- Removednedb-promises@^6.1.0
- Removed@seald-io/binary-search-tree@1.0.3(transitive)
- Removed@seald-io/nedb@4.0.4(transitive)
- Removed@vladmandic/piacme@0.1.30(transitive)
- Removedavailable-typed-arrays@1.0.7(transitive)
- Removedcall-bind@1.0.8(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removedfor-each@0.3.3(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedimmediate@3.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedis-arguments@1.2.0(transitive)
- Removedis-callable@1.2.7(transitive)
- Removedis-generator-function@1.1.0(transitive)
- Removedis-regex@1.2.1(transitive)
- Removedis-typed-array@1.1.15(transitive)
- Removedlie@3.1.1(transitive)
- Removedlocalforage@1.10.0(transitive)
- Removedmoment@2.30.1(transitive)
- Removednedb-promises@6.2.3(transitive)
- Removedpossible-typed-array-names@1.0.0(transitive)
- Removedsafe-regex-test@1.1.0(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedutil@0.12.5(transitive)
- Removedwhich-typed-array@1.1.18(transitive)
- Removedx509.js@1.0.0(transitive)
Updated@vladmandic/piacme@^1.0.2