Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Support IPs and multiple Subject Alt Names in the TLS certificate #190

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The below run time configuration are available, which can be configured either v
- Lightning-RPC Path - Configure the path where `lightning-rpc` file is located. It will default to standard lightning path if not configured
- RPC Command - - Enable additional RPC commands for `/rpc` endpoint
- Domain - An external domain to be used for the self-signed certificate
- IP - A static IP to be used for the self-signed certificate

#### Option 1: Via Config file `cl-rest-config.json`
For running the server, rename the file `sample-cl-rest-config.json` to `cl-rest-config.json`. Following parameters can be configured in the config file:
Expand All @@ -46,6 +47,7 @@ For running the server, rename the file `sample-cl-rest-config.json` to `cl-rest
- LNRPCPATH (Default: ` `)
- RPCCOMMANDS (Default: `["*"]`)
- DOMAIN (Default: `localhost`)
- IP (Default: `127.0.0.1`)
- BIND (Default: `::`)

#### Option 2: With the plugin configuration, if used as a plugin
Expand All @@ -60,6 +62,7 @@ If running as a plugin, configure the below options in your core lightning `conf
- `rest-lnrpcpath`
- `rest-rpc`
- `rest-domain`
- `rest-ip`
- `rest-bind`

Defaults are the same as in option # 1 with the exception that `rest-rpc` is a comma separated string.
Expand Down Expand Up @@ -129,6 +132,10 @@ With the default config, APIs will be served over `https` (a self signed certifi
Sample url: `https://localhost:3001/v1/getinfo/`

Providing a `DOMAIN` to the c-lightning-REST configuration will add the domain as a `subjectAltName` to the openssl certificate, permitting successful certificate validation by users and applications, e.g. Zeus, when connecting to the server at via that domain.
The same thing can be achieved with the `IP` configuration parameter, but for a static IP instead of a DNS domain.

Additionally, both `DOMAIN` and `IP` support specifying multiple comma-separated values, for instance `localhost,example.com,ln.example.com`, or `127.0.0.1,4.5.6.7`.
The resulting TLS certificate will be able to validate HTTPS responses received from any of these domains and IPs.

If you are *upgrading* a server which is already configured, you should first backup and your entire `./certs` directory in case you need to restore it later.
Following this you should delete *only* the `.certs/certificate.pem` and `.certs/key.pem` files, so that new SSL certificates can be generated which take the `subjectAltName` into consideration.
Expand Down
6 changes: 5 additions & 1 deletion cl-rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const PORT = config.PORT;
const EXECMODE = config.EXECMODE;
const DOCPORT = config.DOCPORT;
const DOMAIN = config.DOMAIN || "localhost";
const IP = config.IP || "127.0.0.1";

// Check if any interface on the device has an IPv6 address
const os = require('os');
Expand Down Expand Up @@ -62,9 +63,12 @@ try {
if ( ! fs.existsSync( key ) || ! fs.existsSync( certificate ) ) {
global.logger.log("Generating SSL cert and key");
try {
let subjectAltNames = DOMAIN.split(',').map((domain) => `DNS:${ domain }`).join(',');
subjectAltNames += ',' + IP.split(',').map((ip) => `IP:${ ip }`).join(',');

execSync( 'openssl version', execOptions );
execSync(
`openssl req -x509 -newkey rsa:2048 -keyout ./certs/key.tmp.pem -out ${ certificate } -days 365 -nodes -subj "/C=US/ST=Foo/L=Bar/O=Baz/CN=c-lightning-rest" -addext "subjectAltName = DNS:${ DOMAIN }"`,
`openssl req -x509 -newkey rsa:2048 -keyout ./certs/key.tmp.pem -out ${ certificate } -days 365 -nodes -subj "/C=US/ST=Foo/L=Bar/O=Baz/CN=c-lightning-rest" -addext "subjectAltName = ${ subjectAltNames }"`,
execOptions
);
execSync( `openssl rsa -in ./certs/key.tmp.pem -out ${ key }`, execOptions );
Expand Down
2 changes: 2 additions & 0 deletions clrest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ restPlugin.addOption('rest-execmode', 'production', 'rest exec mode', 'string');
restPlugin.addOption('rest-rpc', ' ', 'allowed rpc commands', 'string');
restPlugin.addOption('rest-lnrpcpath', ' ', 'path for lightning-rpc', 'string');
restPlugin.addOption('rest-domain', ' ', 'domain name for self-signed cert', 'string');
restPlugin.addOption('rest-ip', ' ', 'IP for self-signed cert', 'string');
restPlugin.addOption('rest-bind', ' ', 'Binding address', 'string');

restPlugin.onInit = params => {
Expand All @@ -25,6 +26,7 @@ restPlugin.onInit = params => {
RPCCOMMANDS: params.options['rest-rpc'].trim().split(",").map(s => s.trim()),
LNRPCPATH: params.options['rest-lnrpcpath'],
DOMAIN: params.options['rest-domain'].trim(),
IP: params.options['rest-ip'].trim(),
BIND: params.options['rest-bind'].trim(),
PLUGIN: restPlugin
}
Expand Down
1 change: 1 addition & 0 deletions sample-cl-rest-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"EXECMODE": "production",
"RPCCOMMANDS": ["*"],
"DOMAIN": "localhost",
"IP": "127.0.0.1",
"BIND": "::"
}