Initial fork commit

This commit is contained in:
Pierre Lannoy 2023-12-12 19:45:36 +01:00
commit 34d9abec19
Signed by: Pierre Lannoy
GPG key ID: D27231EF87D53F31
25 changed files with 36 additions and 3840 deletions

View file

@ -2,4 +2,4 @@ HTTP_PORT=80
HTTPS_PORT=443 HTTPS_PORT=443
STAT_PORT=8081 STAT_PORT=8081
BLACKLIST_HOSTS="bad.example,evil.example" BLACKLIST_HOSTS="bad.example,evil.example"
BLACKLIST_REDIRECT="https://forwarddomain.net/blacklisted" BLACKLIST_REDIRECT="https://forwarddomain.net/blacklisted"

2
.gitattributes vendored
View file

@ -1,2 +1,2 @@
# Auto detect text files and perform LF normalization # Auto detect text files and perform LF normalization
* text=auto * text=auto

1
.github/FUNDING.yml vendored
View file

@ -1 +0,0 @@
github: willnode

15
.gitignore vendored
View file

@ -5,27 +5,12 @@ npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover # Directory for instrumented libs generated by jscoverage/JSCover
lib-cov lib-cov
# Coverage directory used by tools like istanbul # Coverage directory used by tools like istanbul
coverage coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration # node-waf configuration
.lock-wscript .lock-wscript

View file

@ -1,3 +0,0 @@
{
"js/ts.implicitProjectConfig.checkJs": true
}

8
CHANGELOG.md Normal file
View file

@ -0,0 +1,8 @@
# Changelog
All notable changes to **Domain-Forward** are documented in this *changelog*.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and **Domain-Forward** adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2023-12-12
Initial commit from fork: https://github.com/willnode/forward-domain

View file

@ -1,36 +0,0 @@
# CHANGES
## v2.5 (2023-04-24)
+ Add `http-status` TXT record option to set HTTP status code. Contributed by [@dzegarra](https://github.com/willnode/forward-domain/pull/4)
+ Improve lock mechanism when a website is verificating certs.
## v2.4 (2023-04-21)
+ Fix global service lock when a website is verificating certs.
+ Update code deps, refactor imports to ESM.
## v2.3 (2022-08-16)
+ Add stat API `s.forwarddomain.net`, separate node script.
## v2.2 (2022-06-16)
+ Moving all parameters to `.env` file
+ Add a domain blacklist mechanism (we received a report that this service is used for phising activity, for the first time)
## v2.1 (2022-01-03)
+ Added `AAAA` record in `r.forwarddomain.net` for IPv6 support. (see [#2](https://github.com/willnode/forward-domain/issues/2#issuecomment-1003831835) for apex domains setup)
## v2.0 (2021-09-21)
+ Dropped `forward-domain-cert-maintainer=` record (as of [LE explanation](https://letsencrypt.org/docs/integration-guide/#who-is-the-subscriber) the provider is the bearer).
+ The software is now keeping LE's account keypair instead of generating new one every restart.
+ Changed IPv4 from `206.189.61.89` to `167.172.5.31` (we use DO's floating IP address now)
+ Changed TXT location to subdomain `_` (because TXT can't be put together with CNAME)
+ Dropped IPv6 record.
## v1.0 (2021-08-23)
+ First release

View file

@ -2,6 +2,7 @@
This guide will walk you through the process of setting up your own instance of ForwardDomain. This is not a guide for setting up a development environment, but rather a guide for setting up a production instance. This guide will walk you through the process of setting up your own instance of ForwardDomain. This is not a guide for setting up a development environment, but rather a guide for setting up a production instance.
## Prerequisites ## Prerequisites
- [Node.js](https://nodejs.org/en/) (version 16 or higher). - [Node.js](https://nodejs.org/en/) (version 16 or higher).

View file

@ -1,6 +1,7 @@
MIT License MIT License
Copyright (c) 2021 Wildan M Copyright (c) 2021 Wildan M
Copyright (c) 2024 Pierre Lannoy / All modifications done after 2023-12-11
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,12 +1,5 @@
# Forward Domain # Forward Domain
[![GitHub Repo stars](https://img.shields.io/github/stars/willnode/forward-domain?style=for-the-badge)](https://github.com/willnode/forward-domain/stargazers)
[![Uptime Robot ratio (30 days)](https://img.shields.io/uptimerobot/ratio/m790428156-91b88afc46cfb86ead3dc56e?style=for-the-badge)](https://stats.uptimerobot.com/AA77Xt9Jx8)
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lp67jpzvabtf8opyzaf.png" alt="Banner" width="600">
> We're back with improvements! See [CHANGES.md](CHANGES.md)
This service forwards domains using HTTP(s) redirects. This service forwards domains using HTTP(s) redirects.
Example scenarios: Example scenarios:

2
app.js
View file

@ -3,11 +3,13 @@ import https from "https";
import app from "./index.js"; import app from "./index.js";
import listener from "./src/client.js"; import listener from "./src/client.js";
import { SniPrepare, SniListener } from "./src/sni.js"; import { SniPrepare, SniListener } from "./src/sni.js";
// production endpoint (use pm2/phusion/whatever) // production endpoint (use pm2/phusion/whatever)
config(); config();
const port80 = parseInt(process.env.HTTP_PORT || "80"); const port80 = parseInt(process.env.HTTP_PORT || "80");
const port443 = parseInt(process.env.HTTPS_PORT || "443"); const port443 = parseInt(process.env.HTTPS_PORT || "443");
const main = async () => { const main = async () => {
await SniPrepare(); await SniPrepare();
const httpsServer = https.createServer({ const httpsServer = https.createServer({

View file

@ -3,7 +3,7 @@ import http from "http";
import listener from "./src/client.js"; import listener from "./src/client.js";
import { isMainProcess } from "./src/util.js"; import { isMainProcess } from "./src/util.js";
// development endpoint (use ngrok) // development endpoint - use ngrok
const server = http.createServer(listener); const server = http.createServer(listener);
if (isMainProcess(import.meta.url)) { if (isMainProcess(import.meta.url)) {
config(); config();

3769
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{ {
"name": "forward-domain", "name": "domain-forrward",
"version": "1.0.0", "version": "1.0.0",
"description": "Public service to forward domain for free", "description": "Public service to forward domain for free",
"main": "app.js", "main": "app.js",
@ -14,7 +14,7 @@
"count": "find .certs -type d | grep '.\\.' | wc -l" "count": "find .certs -type d | grep '.\\.' | wc -l"
}, },
"keywords": [], "keywords": [],
"author": "Wildan Mubarok", "author": "Pierre Lannoy",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"async-lock": "^1.4.0", "async-lock": "^1.4.0",

View file

View file

@ -2,4 +2,4 @@ Copyright 2021 Zachary Balder
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -1,3 +1,3 @@
# certnode # certnode
Modified certnode. Please see https://github.com/zbo14/certnode Modified certnode. Please see https://github.com/zbo14/certnode

View file

@ -10,6 +10,7 @@ import pem from "pem";
import * as common from "./common.js"; import * as common from "./common.js";
import request from "./request.js"; import request from "./request.js";
const createCsr = promisify(pem.createCSR); const createCsr = promisify(pem.createCSR);
/** /**
* Represents a Let's Encrypt account and * Represents a Let's Encrypt account and
* sends requests to get valid TLS certificates. * sends requests to get valid TLS certificates.

View file

@ -13,6 +13,7 @@ export const PRIVATE_KEY_TYPE = 'pkcs8';
export const PUBLIC_KEY_FORMAT = 'pem'; export const PUBLIC_KEY_FORMAT = 'pem';
export const PUBLIC_KEY_PERMISSIONS = 0o666; export const PUBLIC_KEY_PERMISSIONS = 0o666;
export const PUBLIC_KEY_TYPE = 'spki'; export const PUBLIC_KEY_TYPE = 'spki';
/** /**
* @param {crypto.KeyObject} privateKey * @param {crypto.KeyObject} privateKey
* @param {String} [passphrase] * @param {String} [passphrase]
@ -30,6 +31,7 @@ export const exportPrivateKey = (privateKey, passphrase) => {
} }
return privateKey.export(privateKeyOpts); return privateKey.export(privateKeyOpts);
}; };
/** /**
* @param {crypto.KeyObject} publicKey * @param {crypto.KeyObject} publicKey
*/ */
@ -40,6 +42,7 @@ export const exportPublicKey = publicKey => {
format: PUBLIC_KEY_FORMAT format: PUBLIC_KEY_FORMAT
}); });
}; };
/** /**
* @param {String} privateKeyData * @param {String} privateKeyData
* @param {String} [passphrase] * @param {String} [passphrase]
@ -63,6 +66,7 @@ export const importPrivateKey = (privateKeyData, passphrase) => {
throw new Error('Failed to import private key'); throw new Error('Failed to import private key');
} }
}; };
/** /**
* @param {String} publicKeyData * @param {String} publicKeyData
* *
@ -80,6 +84,7 @@ export const importPublicKey = publicKeyData => {
throw new Error('Failed to import public key'); throw new Error('Failed to import public key');
} }
}; };
/** /**
* @param {String} filename * @param {String} filename
* @param {crypto.KeyObject|string} key * @param {crypto.KeyObject|string} key

View file

@ -1,3 +1,3 @@
import Client from './client.js'; import Client from './client.js';
export * from './common.js'; export * from './common.js';
export { Client }; export { Client };

View file

@ -1,4 +1,5 @@
import https from "https"; import https from "https";
/** /**
* @param {string | URL} url * @param {string | URL} url
* @param {import('https').RequestOptions & {data?: string}} [options] * @param {import('https').RequestOptions & {data?: string}} [options]

View file

@ -9,10 +9,12 @@ import { findTxtRecord, isHostBlacklisted, combineURLs } from "./util.js";
* @property {number} expire * @property {number} expire
* @property {number} httpStatus * @property {number} httpStatus
*/ */
/** /**
* @type {Object<string, Cache>} * @type {Object<string, Cache>}
*/ */
const resolveCache = {}; const resolveCache = {};
/** /**
* @param {string} host * @param {string} host
* @returns {Promise<Cache>} * @returns {Promise<Cache>}
@ -42,7 +44,9 @@ async function buildCache(host) {
httpStatus: parseInt(httpStatus), httpStatus: parseInt(httpStatus),
}; };
} }
const acme_prefix = '/.well-known/acme-challenge/'; const acme_prefix = '/.well-known/acme-challenge/';
/** /**
* @type {import('http').RequestListener} * @type {import('http').RequestListener}
*/ */
@ -92,4 +96,5 @@ const listener = async function (req, res) {
res.end(); res.end();
} }
}; };
export default listener; export default listener;

View file

@ -31,6 +31,7 @@ function getCertCachePath(host) {
const hash = md5(host); const hash = md5(host);
return path.join(certsDir, hash.substring(0, 2), hash.substring(2), host); return path.join(certsDir, hash.substring(0, 2), hash.substring(2), host);
} }
/** /**
* @param {string} host * @param {string} host
*/ */
@ -71,6 +72,7 @@ async function buildCache(host) {
}); });
} }
} }
/** /**
* @param {string} servername * @param {string} servername
*/ */
@ -89,6 +91,7 @@ async function getKeyCert(servername) {
cert: cache.cert, cert: cache.cert,
}; };
} }
/** /**
* @param {string} servername * @param {string} servername
* @param {(err: any, cb: tls.SecureContext|undefined) => void} ctx * @param {(err: any, cb: tls.SecureContext|undefined) => void} ctx

View file

@ -2,7 +2,6 @@ import request from "./certnode/lib/request.js";
import crypto from "crypto"; import crypto from "crypto";
import fs from "fs"; import fs from "fs";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
const recordParamDestUrl = 'forward-domain'; const recordParamDestUrl = 'forward-domain';
const recordParamHttpStatus = 'http-status'; const recordParamHttpStatus = 'http-status';
let blacklistURL = null; let blacklistURL = null;

View file

@ -3,6 +3,7 @@ import { execSync } from "child_process";
import http from "http"; import http from "http";
import { isMainProcess } from "./src/util.js"; import { isMainProcess } from "./src/util.js";
const updateStat = function () { const updateStat = function () {
// run npm stat // run npm stat
var buffer = execSync('npm run count'); var buffer = execSync('npm run count');