diff --git a/cyphernodeconf_docker/lib/app.js b/cyphernodeconf_docker/lib/app.js
index fd9fe4c..54920da 100644
--- a/cyphernodeconf_docker/lib/app.js
+++ b/cyphernodeconf_docker/lib/app.js
@@ -14,6 +14,7 @@ const ejsRenderFileAsync = promisify( ejs.renderFile ).bind( ejs );
const html2ansi = require('./html2ansi.js');
const name = require('./name.js');
const Archive = require('./archive.js');
+const TorGen = require('./torgen.js');
const ApiKey = require('./apikey.js');
const Cert = require('./cert.js');
const htpasswd = require( './htpasswd.js');
@@ -271,6 +272,12 @@ module.exports = class App {
async processProps() {
+ // TOR...
+ if( this.isChecked( 'features', 'tor' ) ) {
+ const torgen = new TorGen(this.destinationPath( path.join( destinationDirName, 'tor/hidden_service' ) ));
+ this.sessionData.tor_hostname = await torgen.generateTorFiles();
+ }
+
// creates keys if they don't exist or we say so.
if( this.config.data.gatekeeper_recreatekeys ||
this.config.data.gatekeeper_keys.configEntries.length===0 ) {
@@ -479,7 +486,7 @@ module.exports = class App {
networks: ['cyphernodenet', 'cyphernodeappsnet'],
docker: "cyphernode/tor:" + this.config.docker_versions['cyphernode/tor'],
extra: {
- hostname: 'tor_hostname_placeholder',
+ hostname: this.sessionData.tor_hostname,
}
},
otsclient: {
diff --git a/cyphernodeconf_docker/lib/torgen.js b/cyphernodeconf_docker/lib/torgen.js
new file mode 100644
index 0000000..512f87d
--- /dev/null
+++ b/cyphernodeconf_docker/lib/torgen.js
@@ -0,0 +1,47 @@
+const spawn = require('child_process').spawn;
+const stringio = require('@rauschma/stringio');
+const fs = require('fs');
+const chalk = require('chalk');
+
+module.exports = class TorGen {
+
+ constructor( path ) {
+ this.path = path || './'
+ }
+
+ async generateTorFiles() {
+// console.log(chalk.green( 'TOR datapath=' + this.path ));
+
+ if( !fs.existsSync(this.path) ) {
+ console.log(chalk.green( 'Creating TOR Hidden Service directory...' ));
+ fs.mkdirSync(this.path, { recursive: true });
+ }
+
+ if( !fs.existsSync(this.path + '/hostname') ) {
+
+ console.log(chalk.bold.green( 'Generating TOR Hidden Service secret key, public key and hostname...' ));
+
+ const torgenbin = spawn('./torgen/torgen', [this.path]);
+ try {
+ await stringio.onExit( torgenbin );
+ } catch( err ) {
+ console.log(chalk.bold.red('Error: ' + err) );
+ return "";
+ }
+
+// console.log(chalk.bold.green( 'Generated TOR Hidden Service secret key, public key and hostname.' ));
+
+ } else {
+ console.log(chalk.red('TOR config files already exist, skipping generation') );
+ }
+
+ try {
+ var data = fs.readFileSync(this.path + '/hostname', 'utf8');
+ return data.slice(0, -1);
+ } catch (err) {
+ console.log(chalk.bold.red('Error: ' + err) );
+ return "";
+ }
+
+ }
+}
diff --git a/cyphernodeconf_docker/prompters/040_tor.js b/cyphernodeconf_docker/prompters/040_tor.js
index 198f440..41c5fdf 100644
--- a/cyphernodeconf_docker/prompters/040_tor.js
+++ b/cyphernodeconf_docker/prompters/040_tor.js
@@ -27,22 +27,22 @@ module.exports = {
name: 'torifyables',
message: prefix()+'What features do you want to TORify?'+utils.getHelp('torifyables'),
choices: utils.torifyableChoices()
+ },
+ {
+ when: featureCondition,
+ type: 'checkbox',
+ name: 'clearnet',
+ default: utils.getDefault( 'clearnet' ),
+ message: prefix()+'What features do you want to allow using clearnet?'+utils.getHelp('clearnet'),
+ choices: [{
+ name: "Bitcoin Node",
+ value: "clearnet_bitcoinnode"
+ },{
+ name: "LN Node",
+ value: "clearnet_lnnode"
+ }]
}];
},
- {
- when: featureCondition,
- type: 'checkbox',
- name: 'clearnet',
- default: utils.getDefault( 'clearnet' ),
- message: prefix()+'What features do you want to allow using clearnet?'+utils.getHelp('clearnet'),
- choices: [{
- name: "Bitcoin Node",
- value: "clearnet_bitcoinnode"
- },{
- name: "LN Node",
- value: "clearnet_lnnode"
- }]
- },
templates: function( props ) {
return [ 'torrc' ];
}
@@ -67,11 +67,11 @@ module.exports = {
// - Address Watches Callbacks (webhooks)
// - TXID Watches Callbacks (webhooks)
-Certain services can also use clearnet. What do you want to allow to use clearnet?
-- Bitcoin Node
-- LN Node
-
-Do you want to announce your LN node onion address and/or IP address?
-
-What is your public IP address?
+// Certain services can also use clearnet. What do you want to allow to use clearnet?
+// - Bitcoin Node
+// - LN Node
+//
+// Do you want to announce your LN node onion address and/or IP address?
+//
+// What is your public IP address?
diff --git a/cyphernodeconf_docker/schema/config-v0.2.3.json b/cyphernodeconf_docker/schema/config-v0.2.3.json
index 16622a4..c4f9c1b 100644
--- a/cyphernodeconf_docker/schema/config-v0.2.3.json
+++ b/cyphernodeconf_docker/schema/config-v0.2.3.json
@@ -99,7 +99,7 @@
},
"then": {
"required": [
- "tor_datapath"
+ "tor_datapath",
"torifyables",
"clearnet"
]
diff --git a/cyphernodeconf_docker/templates/lightning/c-lightning/config b/cyphernodeconf_docker/templates/lightning/c-lightning/config
index e4df753..f6bce82 100644
--- a/cyphernodeconf_docker/templates/lightning/c-lightning/config
+++ b/cyphernodeconf_docker/templates/lightning/c-lightning/config
@@ -16,10 +16,10 @@ rgb=<%= lightning_nodecolor %>
addr=0.0.0.0:9735
-<% if ( features.indexOf('tor_lnnode') !== -1 ) { %>
+<% if ( torifyables.indexOf('tor_lnnode') !== -1 ) { %>
#tor
proxy=tor:9050
-<% if ( features.indexOf('clearnet_lnnode') == -1 ) { %>
+<% if ( clearnet.indexOf('clearnet_lnnode') == -1 ) { %>
always-use-proxy=true
<% } %>
#disable-dns
@@ -29,10 +29,11 @@ announce-addr=<%= locals.lightning_external_ip %>:9735
<% } %>
<% } %>
<% if (lightning_announce) { %>
- <% if ( features.indexOf('tor_lnnode') !== -1 ) { %>
+ <% if ( torifyables.indexOf('tor_lnnode') !== -1 ) { %>
announce-addr=<%= locals.lightning_external_ip %>:1234
- <% if ( features.indexOf('clearnet_lnnode') == -1 ) { %>
- announce-addr=onionaddress:9735
+ <% if ( clearnet.indexOf('clearnet_lnnode') == -1 ) { %>
+ announce-addr=<%= locals.tor_hostname %>:9735
+
<% } %>
<% } %>
<% } %>
diff --git a/cyphernodeconf_docker/templates/tor/torrc b/cyphernodeconf_docker/templates/tor/torrc
index 18a09eb..f218bf5 100644
--- a/cyphernodeconf_docker/templates/tor/torrc
+++ b/cyphernodeconf_docker/templates/tor/torrc
@@ -1,4 +1,4 @@
-<% if ( features.indexOf('tor_hiddenservice') !== -1 ) { %>
+<% if ( torifyables.indexOf('tor_hiddenservice') !== -1 ) { %>
HiddenServiceDir /tor/hidden_service/
HiddenServiceVersion 3
HiddenServicePort 80 traefik:80
diff --git a/cyphernodeconf_docker/torgen/torgen.go b/cyphernodeconf_docker/torgen/torgen.go
index 8eab44a..6a3bd6b 100644
--- a/cyphernodeconf_docker/torgen/torgen.go
+++ b/cyphernodeconf_docker/torgen/torgen.go
@@ -25,101 +25,101 @@
package main
import (
- "bytes"
- "encoding/base32"
- "fmt"
- "os"
- "path"
- "strings"
+ "bytes"
+ "encoding/base32"
+ "fmt"
+ "os"
+ "path"
+ "strings"
- "crypto/ed25519"
- "crypto/sha512"
+ "crypto/ed25519"
+ "crypto/sha512"
- "golang.org/x/crypto/sha3"
+ "golang.org/x/crypto/sha3"
)
func main() {
- path := path.Clean(os.Args[1])
- fmt.Println("path=" + path)
+ path := path.Clean(os.Args[1])
+ fmt.Println("path=" + path)
- /**
- About the key files format: https://gitweb.torproject.org/tor.git/tree/src/lib/crypt_ops/crypto_format.c?h=tor-0.4.1.6#n34
+ /**
+ About the key files format: https://gitweb.torproject.org/tor.git/tree/src/lib/crypt_ops/crypto_format.c?h=tor-0.4.1.6#n34
- Write the datalen bytes from data to the file named
- fname in the tagged-data format. This format contains a
- 32-byte header, followed by the data itself. The header is the
- NUL-padded string "== typestring: tag ==". The length
- of typestring and tag must therefore be no more than
- 24.
+ Write the datalen bytes from data to the file named
+ fname in the tagged-data format. This format contains a
+ 32-byte header, followed by the data itself. The header is the
+ NUL-padded string "== typestring: tag ==". The length
+ of typestring and tag must therefore be no more than
+ 24.
- About the secret key format: https://gitweb.torproject.org/tor.git/tree/src/lib/crypt_ops/crypto_ed25519.h?h=tor-0.4.1.6#n29
+ About the secret key format: https://gitweb.torproject.org/tor.git/tree/src/lib/crypt_ops/crypto_ed25519.h?h=tor-0.4.1.6#n29
- Note that we store secret keys in an expanded format that doesn't match
- the format from standard ed25519. Ed25519 stores a 32-byte value k and
- expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
- of the base point, and second 32 bytes as an input to a hash function
- for deriving r. But because we implement key blinding, we need to store
- keys in the 64-byte expanded form.
- **/
+ Note that we store secret keys in an expanded format that doesn't match
+ the format from standard ed25519. Ed25519 stores a 32-byte value k and
+ expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
+ of the base point, and second 32 bytes as an input to a hash function
+ for deriving r. But because we implement key blinding, we need to store
+ keys in the 64-byte expanded form.
+ **/
- // Key pair generation
- fmt.Println("Generating ed25519 keys...")
- publicKey, privateKey, _ := ed25519.GenerateKey(nil)
+ // Key pair generation
+ fmt.Println("Generating ed25519 keys...")
+ publicKey, privateKey, _ := ed25519.GenerateKey(nil)
- // Convert seed to expanded private key...
- // Ref.: https://gitweb.torproject.org/tor.git/tree/src/ext/ed25519/donna/ed25519_tor.c?h=tor-0.4.1.6#n61
- // Ref.: https://gitweb.torproject.org/tor.git/tree/src/ext/curve25519_donna/README?h=tor-0.4.1.6#n28
- fmt.Println("Converting keys for TOR...")
- h := sha512.Sum512(privateKey[:32])
- h[0] &= 248
- h[31] &= 127
- h[31] |= 64
+ // Convert seed to expanded private key...
+ // Ref.: https://gitweb.torproject.org/tor.git/tree/src/ext/ed25519/donna/ed25519_tor.c?h=tor-0.4.1.6#n61
+ // Ref.: https://gitweb.torproject.org/tor.git/tree/src/ext/curve25519_donna/README?h=tor-0.4.1.6#n28
+ fmt.Println("Converting keys for TOR...")
+ h := sha512.Sum512(privateKey[:32])
+ h[0] &= 248
+ h[31] &= 127
+ h[31] |= 64
- // Create the Tor Hidden Service private key file
- fmt.Println("Creating secret file...")
- var fileBytes bytes.Buffer
- fileBytes.Write([]byte("== ed25519v1-secret: type0 =="))
- fileBytes.Write(bytes.Repeat([]byte{0x00}, 3))
- fileBytes.Write(h[:])
+ // Create the Tor Hidden Service private key file
+ fmt.Println("Creating secret file...")
+ var fileBytes bytes.Buffer
+ fileBytes.Write([]byte("== ed25519v1-secret: type0 =="))
+ fileBytes.Write(bytes.Repeat([]byte{0x00}, 3))
+ fileBytes.Write(h[:])
- prvFile, _ := os.Create(path + "/hs_ed25519_secret_key")
- fileBytes.WriteTo(prvFile)
- prvFile.Close()
+ prvFile, _ := os.Create(path + "/hs_ed25519_secret_key")
+ fileBytes.WriteTo(prvFile)
+ prvFile.Close()
- // Create the Tor Hidden Service public key file
- fmt.Println("Creating public file...")
- fileBytes.Reset()
- fileBytes.Write([]byte("== ed25519v1-public: type0 =="))
- fileBytes.Write(bytes.Repeat([]byte{0x00}, 3))
- fileBytes.Write([]byte(publicKey))
+ // Create the Tor Hidden Service public key file
+ fmt.Println("Creating public file...")
+ fileBytes.Reset()
+ fileBytes.Write([]byte("== ed25519v1-public: type0 =="))
+ fileBytes.Write(bytes.Repeat([]byte{0x00}, 3))
+ fileBytes.Write([]byte(publicKey))
- pubFile, _ := os.Create(path + "/hs_ed25519_public_key")
- fileBytes.WriteTo(pubFile)
- pubFile.Close()
+ pubFile, _ := os.Create(path + "/hs_ed25519_public_key")
+ fileBytes.WriteTo(pubFile)
+ pubFile.Close()
- // From https://github.com/rdkr/oniongen-go
- // checksum = H(".onion checksum" || pubkey || version)
- fmt.Println("Creating onion address...")
- var checksumBytes bytes.Buffer
- checksumBytes.Write([]byte(".onion checksum"))
- checksumBytes.Write([]byte(publicKey))
- checksumBytes.Write([]byte{0x03})
- checksum := sha3.Sum256(checksumBytes.Bytes())
+ // From https://github.com/rdkr/oniongen-go
+ // checksum = H(".onion checksum" || pubkey || version)
+ fmt.Println("Creating onion address...")
+ var checksumBytes bytes.Buffer
+ checksumBytes.Write([]byte(".onion checksum"))
+ checksumBytes.Write([]byte(publicKey))
+ checksumBytes.Write([]byte{0x03})
+ checksum := sha3.Sum256(checksumBytes.Bytes())
- // onion_address = base32(pubkey || checksum || version)
- var onionAddressBytes bytes.Buffer
- onionAddressBytes.Write([]byte(publicKey))
- onionAddressBytes.Write([]byte(checksum[:2]))
- onionAddressBytes.Write([]byte{0x03})
- onionAddress := base32.StdEncoding.EncodeToString(onionAddressBytes.Bytes())
+ // onion_address = base32(pubkey || checksum || version)
+ var onionAddressBytes bytes.Buffer
+ onionAddressBytes.Write([]byte(publicKey))
+ onionAddressBytes.Write([]byte(checksum[:2]))
+ onionAddressBytes.Write([]byte{0x03})
+ onionAddress := base32.StdEncoding.EncodeToString(onionAddressBytes.Bytes())
- // Create the Tor Hidden Service hostname file
- fmt.Println("Creating onion address file...")
- nameFile, _ := os.Create(path + "/hostname")
- nameFile.WriteString(strings.ToLower(onionAddress) + ".onion\n")
- nameFile.Close()
+ // Create the Tor Hidden Service hostname file
+ fmt.Println("Creating onion address file...")
+ nameFile, _ := os.Create(path + "/hostname")
+ nameFile.WriteString(strings.ToLower(onionAddress) + ".onion\n")
+ nameFile.Close()
- fmt.Println("Done!")
+ fmt.Println("Done!")
}
diff --git a/dist/setup.sh b/dist/setup.sh
index 680c91e..2be2723 100755
--- a/dist/setup.sh
+++ b/dist/setup.sh
@@ -407,6 +407,7 @@ install_docker() {
fi
copy_file $cyphernodeconf_filepath/tor/torrc $TOR_DATAPATH/torrc 1 $SUDO_REQUIRED
+ copy_file $cyphernodeconf_filepath/tor/hidden_service/* $TOR_DATAPATH/hidden_service/ 1 $SUDO_REQUIRED
fi
@@ -721,22 +722,6 @@ install() {
fi
}
-manage_tor_keys() {
- until [ -f hostname ] && [ -f hs_ed25519_secret_key ] && [ -f hs_ed25519_public_key ]
-do
- sleep 0.1
- max=$(($max-1))
- if [[ $max == 0 ]]
- then
- # Kill Tor on timeout and exit with error code 1.
- kill -9 $pid >/dev/null 2>&1
- rm -f torrc hostname hs_ed25519_secret_key hs_ed25519_public_key
- popd >/dev/null 2>&1
- exit 1
- fi
-done
-}
-
CONFIGURE=0
INSTALL=0
RECREATE=0
@@ -829,10 +814,6 @@ if [[ $CONFIGURE == 1 ]]; then
configure $RECREATE
fi
-# If TOR is installed, we want to create the Hidden Serivce hostname now to make it
-# available to LN and whatever needs it at this point...
-manage_tor_keys
-
if [[ -f "$cyphernodeconf_filepath/installer/config.sh" ]]; then
. "$cyphernodeconf_filepath/installer/config.sh"
fi
diff --git a/proxy_docker/app/script/requesthandler.sh b/proxy_docker/app/script/requesthandler.sh
index c62a761..613545c 100644
--- a/proxy_docker/app/script/requesthandler.sh
+++ b/proxy_docker/app/script/requesthandler.sh
@@ -79,12 +79,7 @@ main() {
installation_info)
# GET http://192.168.111.152:8080/info
if [ -f "$DB_PATH/info.json" ]; then
- if [ -f "tor/hidden_service/hostname" ]; then
- # Replace tor_hostname_placeholder with actual tor hostname from tor file
- response=$(sed "s/tor_hostname_placeholder/`tr -d '\n\r' < tor/hidden_service/hostname`/g" "$DB_PATH/info.json")
- else
- response=$(cat "$DB_PATH/info.json")
- fi
+ response=$(cat "$DB_PATH/info.json")
else
response='{ "error": "missing installation data" }'
fi