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

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

@ -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,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');