Make TOR optional, add info in welcome page, ability for notifier to bypass

This commit is contained in:
kexkey
2019-11-08 16:03:14 -05:00
committed by kexkey
parent 477c93468f
commit 58b80e1d3b
16 changed files with 130 additions and 27 deletions

View File

@@ -6,5 +6,9 @@
{ {
"name": "Opentimestamps client", "name": "Opentimestamps client",
"value": "otsclient" "value": "otsclient"
},
{
"name": "Tor Hidden Service/Gateway",
"value": "tor"
} }
] ]

View File

@@ -466,6 +466,13 @@ module.exports = class App {
const optional_features = []; const optional_features = [];
const optional_features_data = { const optional_features_data = {
tor: {
networks: ['cyphernodenet', 'cyphernodeappsnet'],
docker: "cyphernode/tor:" + this.config.docker_versions['cyphernode/tor'],
extra: {
hostname: 'tor_hostname_placeholder',
}
},
otsclient: { otsclient: {
docker: "cyphernode/otsclient:" + this.config.docker_versions['cyphernode/otsclient'] docker: "cyphernode/otsclient:" + this.config.docker_versions['cyphernode/otsclient']
}, },

View File

@@ -19,6 +19,6 @@ module.exports = {
]; ];
}, },
templates: function( props ) { templates: function( props ) {
return [ 'torrc' ]; return [ 'torrc', 'curlcfg' ];
} }
}; };

View File

@@ -69,7 +69,7 @@ module.exports = {
message: prefix()+'Custom path for traefik data?'+utils.getHelp('traefik_datapath_custom'), message: prefix()+'Custom path for traefik data?'+utils.getHelp('traefik_datapath_custom'),
}, },
{ {
when: installerDocker, when: (props)=>{ return installerDocker(props) && props.features.indexOf('tor') !== -1 },
type: 'list', type: 'list',
name: 'tor_datapath', name: 'tor_datapath',
default: utils.getDefault( 'tor_datapath' ), default: utils.getDefault( 'tor_datapath' ),
@@ -98,7 +98,7 @@ module.exports = {
message: prefix()+'Where do you want to store your tor data?'+utils.getHelp('tor_datapath'), message: prefix()+'Where do you want to store your tor data?'+utils.getHelp('tor_datapath'),
}, },
{ {
when: (props)=>{ return installerDocker(props) && (props.tor_datapath === '_custom') }, when: (props)=>{ return installerDocker(props) && props.features.indexOf('tor') !== -1 && props.otsclient_datapath === '_custom' },
type: 'input', type: 'input',
name: 'tor_datapath_custom', name: 'tor_datapath_custom',
default: utils.getDefault( 'tor_datapath_custom' ), default: utils.getDefault( 'tor_datapath_custom' ),

View File

@@ -33,8 +33,7 @@
"proxy_datapath", "proxy_datapath",
"traefik_datapath", "traefik_datapath",
"traefik_http_port", "traefik_http_port",
"traefik_https_port", "traefik_https_port"
"tor_datapath"
], ],
"allOf": [ "allOf": [
{ {
@@ -126,6 +125,24 @@
"otsclient_datapath" "otsclient_datapath"
] ]
} }
},
{
"if": {
"properties": {
"features": {
"contains": {
"enum": [
"tor"
]
}
}
}
},
"then": {
"required": [
"tor_datapath"
]
}
} }
], ],
"properties": { "properties": {
@@ -164,13 +181,15 @@
"type": "string", "type": "string",
"enum": [ "enum": [
"lightning", "lightning",
"otsclient" "otsclient",
"tor"
], ],
"title": "The feature", "title": "The feature",
"default": "", "default": "",
"examples": [ "examples": [
"lightning", "lightning",
"otsclient" "otsclient",
"tor"
] ]
} }
}, },

View File

@@ -15,9 +15,12 @@ txindex=1
zmqpubrawblock=tcp://0.0.0.0:18501 zmqpubrawblock=tcp://0.0.0.0:18501
zmqpubrawtx=tcp://0.0.0.0:18502 zmqpubrawtx=tcp://0.0.0.0:18502
<% if ( features.indexOf('tor') !== -1 ) { %>
#tor #tor
#proxy=127.0.0.1:9050 proxy=tor:9050
#listen=1 onlynet=onion
listen=1
<% } %>
maxmempool=64 maxmempool=64
dbcache=64 dbcache=64

View File

@@ -7,7 +7,10 @@ PROXY_DATAPATH=<%= proxy_datapath %>
GATEKEEPER_DATAPATH=<%= gatekeeper_datapath %> GATEKEEPER_DATAPATH=<%= gatekeeper_datapath %>
GATEKEEPER_PORT=<%= gatekeeper_port %> GATEKEEPER_PORT=<%= gatekeeper_port %>
TRAEFIK_DATAPATH=<%= traefik_datapath %> TRAEFIK_DATAPATH=<%= traefik_datapath %>
FEATURE_TOR=<%= (features.indexOf('tor') != -1)?'true':'false' %>
<% if ( features.indexOf('tor') !== -1 ) { %>
TOR_DATAPATH=<%= tor_datapath %> TOR_DATAPATH=<%= tor_datapath %>
<% } %>
DOCKER_MODE=<%= docker_mode %> DOCKER_MODE=<%= docker_mode %>
RUN_AS_USER=<%= run_as_different_user?username:'' %> RUN_AS_USER=<%= run_as_different_user?username:'' %>
CLEANUP=<%= installer_cleanup?'true':'false' %> CLEANUP=<%= installer_cleanup?'true':'false' %>

View File

@@ -73,6 +73,9 @@ services:
<% if ( features.indexOf('otsclient') !== -1 ) { %> <% if ( features.indexOf('otsclient') !== -1 ) { %>
- "<%= otsclient_datapath %>:/proxy/otsfiles" - "<%= otsclient_datapath %>:/proxy/otsfiles"
<% } %> <% } %>
<% if ( features.indexOf('tor') !== -1 ) { %>
- "<%= tor_datapath %>:/proxy/tor"
<% } %>
networks: networks:
- cyphernodenet - cyphernodenet
restart: always restart: always
@@ -119,6 +122,8 @@ services:
notifier: notifier:
image: cyphernode/notifier:<%= notifier_version %> image: cyphernode/notifier:<%= notifier_version %>
command: $USER ./startnotifier.sh command: $USER ./startnotifier.sh
volumes:
- "<%= tor_datapath %>/curlcfg:/notifier/curlcfg"
networks: networks:
- cyphernodenet - cyphernodenet
- cyphernodeappsnet - cyphernodeappsnet
@@ -233,6 +238,7 @@ services:
# placement: # placement:
# constraints: [node.hostname==dev] # constraints: [node.hostname==dev]
<% if ( features.indexOf('tor') !== -1 ) { %>
########################## ##########################
# TOR # # TOR #
########################## ##########################
@@ -251,6 +257,7 @@ services:
# deploy: # deploy:
# placement: # placement:
# constraints: [node.hostname==dev] # constraints: [node.hostname==dev]
<% } %>
<% if ( features.indexOf('lightning') !== -1 && lightning_implementation === 'c-lightning' ) { %> <% if ( features.indexOf('lightning') !== -1 && lightning_implementation === 'c-lightning' ) { %>
########################## ##########################

View File

@@ -100,7 +100,7 @@ checknotifier() {
local response local response
local returncode local returncode
response=$(mosquitto_rr -h broker -W 15 -t notifier -e "response/$$" -m "{\"response-topic\":\"response/$$\",\"cmd\":\"web\",\"url\":\"http://proxy:8888/helloworld\"}") response=$(mosquitto_rr -h broker -W 15 -t notifier -e "response/$$" -m "{\"response-topic\":\"response/$$\",\"cmd\":\"web\",\"url\":\"http://proxy:8888/helloworld\",\"torbypass\":true}")
returncode=$? returncode=$?
[ "${returncode}" -ne "0" ] && return 115 [ "${returncode}" -ne "0" ] && return 115
http_code=$(echo "${response}" | jq -r ".http_code") http_code=$(echo "${response}" | jq -r ".http_code")
@@ -124,6 +124,18 @@ checkots() {
return 0 return 0
} }
checktor() {
echo -en "\r\n\e[1;36mTesting TOR... " > /dev/console
local rc
rc=$(curl -s -o /dev/null -w "%{http_code}" --socks5-hostname tor:9050 http://expyuzz4wqqyqhjn.onion/)
[ "${rc}" -ne "200" ] && return 250
echo -e "\e[1;36mTOR rocks!" > /dev/console
return 0
}
checkbitcoinnode() { checkbitcoinnode() {
echo -en "\r\n\e[1;36mTesting Bitcoin... " > /dev/console echo -en "\r\n\e[1;36mTesting Bitcoin... " > /dev/console
local rc local rc
@@ -161,12 +173,12 @@ checkservice() {
while : while :
do do
outcome=0 outcome=0
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
echo -e " \e[0;32mVerifying \e[0;33m${container}\e[0;32m..." > /dev/console echo -e " \e[0;32mVerifying \e[0;33m${container}\e[0;32m..." > /dev/console
(ping -c 10 ${container} 2> /dev/null | grep "0% packet loss" > /dev/null) & (ping -c 10 ${container} 2> /dev/null | grep "0% packet loss" > /dev/null) &
eval ${container}=$! eval ${container}=$!
done done
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
eval wait '$'${container} ; returncode=$? ; outcome=$((${outcome} + ${returncode})) eval wait '$'${container} ; returncode=$? ; outcome=$((${outcome} + ${returncode}))
eval c_${container}=${returncode} eval c_${container}=${returncode}
done done
@@ -185,10 +197,11 @@ checkservice() {
# { "name": "proxycron", "active":true }, # { "name": "proxycron", "active":true },
# { "name": "pycoin", "active":true }, # { "name": "pycoin", "active":true },
# { "name": "otsclient", "active":true }, # { "name": "otsclient", "active":true },
# { "name": "tor", "active":true },
# { "name": "bitcoin", "active":true }, # { "name": "bitcoin", "active":true },
# { "name": "lightning", "active":true }, # { "name": "lightning", "active":true },
# ] # ]
for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do for container in gatekeeper proxy proxycron broker notifier pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %><%= (features.indexOf('tor') != -1)?'tor ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
[ -n "${result}" ] && result="${result}," [ -n "${result}" ] && result="${result},"
result="${result}{\"name\":\"${container}\",\"active\":" result="${result}{\"name\":\"${container}\",\"active\":"
eval "returncode=\$c_${container}" eval "returncode=\$c_${container}"
@@ -245,6 +258,7 @@ feature_status() {
# { "name": "proxycron", "active":true }, # { "name": "proxycron", "active":true },
# { "name": "pycoin", "active":true }, # { "name": "pycoin", "active":true },
# { "name": "otsclient", "active":true }, # { "name": "otsclient", "active":true },
# { "name": "tor", "active":true },
# { "name": "bitcoin", "active":true }, # { "name": "bitcoin", "active":true },
# { "name": "lightning", "active":true }, # { "name": "lightning", "active":true },
# ], # ],
@@ -252,6 +266,7 @@ feature_status() {
# { "name": "gatekeeper", "working":true }, # { "name": "gatekeeper", "working":true },
# { "name": "pycoin", "working":true }, # { "name": "pycoin", "working":true },
# { "name": "otsclient", "working":true }, # { "name": "otsclient", "working":true },
# { "name": "tor", "working":true },
# { "name": "bitcoin", "working":true }, # { "name": "bitcoin", "working":true },
# { "name": "lightning", "working":true }, # { "name": "lightning", "working":true },
# ] # ]
@@ -285,6 +300,7 @@ fi
# { "name": "gatekeeper", "working":true }, # { "name": "gatekeeper", "working":true },
# { "name": "pycoin", "working":true }, # { "name": "pycoin", "working":true },
# { "name": "otsclient", "working":true }, # { "name": "otsclient", "working":true },
# { "name": "tor", "working":true },
# { "name": "bitcoin", "working":true }, # { "name": "bitcoin", "working":true },
# { "name": "lightning", "working":true }, # { "name": "lightning", "working":true },
# ] # ]
@@ -366,6 +382,23 @@ finalreturncode=$((${returncode} | ${finalreturncode}))
result="${result}$(feature_status ${returncode} 'OTSclient error!')}" result="${result}$(feature_status ${returncode} 'OTSclient error!')}"
<% } %> <% } %>
<% if (features.indexOf('tor') != -1) { %>
#############################
# TOR #
#############################
result="${result},{\"coreFeature\":false, \"name\":\"tor\",\"working\":"
status=$(echo "{${containers}}" | jq ".containers[] | select(.name == \"tor\") | .active")
if [[ "${workingproxy}" = "true" && "${status}" = "true" ]]; then
timeout_feature checktor
returncode=$?
else
returncode=1
fi
finalreturncode=$((${returncode} | ${finalreturncode}))
result="${result}$(feature_status ${returncode} 'TOR error!')}"
<% } %>
############################# #############################
# BITCOIN # # BITCOIN #
############################# #############################

View File

@@ -0,0 +1,3 @@
<% if ( features.indexOf('tor') !== -1 ) { %>
socks5-hostname=tor:9050
<% } %>

View File

@@ -4,7 +4,8 @@
"docker_versions": {}, "docker_versions": {},
"features": [ "features": [
"lightning", "lightning",
"otsclient" "otsclient",
"tor"
], ],
"net": "testnet", "net": "testnet",
"use_xpub": true, "use_xpub": true,

17
dist/setup.sh vendored
View File

@@ -398,14 +398,17 @@ install_docker() {
copy_file $cyphernodeconf_filepath/traefik/htpasswd $TRAEFIK_DATAPATH/htpasswd 1 $SUDO_REQUIRED copy_file $cyphernodeconf_filepath/traefik/htpasswd $TRAEFIK_DATAPATH/htpasswd 1 $SUDO_REQUIRED
if [ ! -d $TOR_DATAPATH ]; then if [[ $FEATURE_TOR == true ]]; then
step " create $TOR_DATAPATH" if [ ! -d $TOR_DATAPATH ]; then
sudo_if_required mkdir -p $TOR_DATAPATH/hidden_service step " create $TOR_DATAPATH"
sudo_if_required chmod 700 $TOR_DATAPATH/hidden_service sudo_if_required mkdir -p $TOR_DATAPATH/hidden_service
next sudo_if_required chmod 700 $TOR_DATAPATH/hidden_service
fi next
fi
copy_file $cyphernodeconf_filepath/tor/torrc $TOR_DATAPATH/torrc 1 $SUDO_REQUIRED copy_file $cyphernodeconf_filepath/tor/torrc $TOR_DATAPATH/torrc 1 $SUDO_REQUIRED
copy_file $cyphernodeconf_filepath/tor/curlcfg $TOR_DATAPATH/curlcfg 1 $SUDO_REQUIRED
fi
if [ ! -d $PROXY_DATAPATH ]; then if [ ! -d $PROXY_DATAPATH ]; then

View File

@@ -44,6 +44,7 @@ Current components in Cyphernode:
- Bitcoin: Bitcoin Core node. Cyphernode uses a watching wallet for watchers (no funds) and a spending wallet for spending. Mandatory component, but optionally part of Cyphernode installation, as we can use an already running Bitcoin Core node. - Bitcoin: Bitcoin Core node. Cyphernode uses a watching wallet for watchers (no funds) and a spending wallet for spending. Mandatory component, but optionally part of Cyphernode installation, as we can use an already running Bitcoin Core node.
- Lightning: optional. C-Lightning node. The LN node will use the Bitcoin node for its tasks. - Lightning: optional. C-Lightning node. The LN node will use the Bitcoin node for its tasks.
- OTSclient: optional. Used to stamp hashes on the Bitcoin blockchain. - OTSclient: optional. Used to stamp hashes on the Bitcoin blockchain.
- TOR: optional. Used to serve traefik as a HiddenService as well as Internet Gateway.
Future components: Future components:

View File

@@ -75,6 +75,7 @@ echo "arch_docker=$arch_docker\n"
image "gatekeeper" "api_auth_docker/" ${arch_docker} \ image "gatekeeper" "api_auth_docker/" ${arch_docker} \
&& image "proxycron" "cron_docker/" ${arch_docker} \ && image "proxycron" "cron_docker/" ${arch_docker} \
&& image "otsclient" "otsclient_docker/" ${arch_docker} \ && image "otsclient" "otsclient_docker/" ${arch_docker} \
&& image "tor" "tor_docker/" ${arch_docker} \
&& image "proxy" "proxy_docker/" ${arch_docker} \ && image "proxy" "proxy_docker/" ${arch_docker} \
&& image "notifier" "notifier_docker/" ${arch_docker} \ && image "notifier" "notifier_docker/" ${arch_docker} \
&& image "pycoin" "pycoin_docker/" ${arch_docker} \ && image "pycoin" "pycoin_docker/" ${arch_docker} \
@@ -89,6 +90,7 @@ image "gatekeeper" "api_auth_docker/" ${arch_docker} \
manifest "gatekeeper" \ manifest "gatekeeper" \
&& manifest "proxycron" \ && manifest "proxycron" \
&& manifest "otsclient" \ && manifest "otsclient" \
&& manifest "tor" \
&& manifest "proxy" \ && manifest "proxy" \
&& manifest "notifier" \ && manifest "notifier" \
&& manifest "pycoin" \ && manifest "pycoin" \

View File

@@ -8,6 +8,7 @@ web() {
local msg=${1} local msg=${1}
local url local url
local body local body
local torbypass
local returncode local returncode
local response local response
local result local result
@@ -28,7 +29,15 @@ web() {
trace "[web] no body, GET request" trace "[web] no body, GET request"
fi fi
response=$(curl_it "${url}" "${body}") torbypass=$(echo ${msg} | jq -e ".torbypass")
# jq -e will have a return code of 1 if the supplied tag is null.
if [ "$?" -ne "0" ]; then
# torbypass tag null
torbypass=false
fi
trace "[web] torbypass=${torbypass}"
response=$(curl_it "${url}" "${body}", "${torbypass}")
returncode=$? returncode=$?
trace_rc ${returncode} trace_rc ${returncode}
@@ -42,17 +51,24 @@ curl_it() {
local url=$(echo "${1}" | tr -d '"') local url=$(echo "${1}" | tr -d '"')
local data=${2} local data=${2}
local torbypass=${3}
local returncode local returncode
local response local response
local rnd=$(dd if=/dev/urandom bs=5 count=1 | xxd -pc 5) local rnd=$(dd if=/dev/urandom bs=5 count=1 | xxd -pc 5)
if [ "${torbypass}" = "true" ]; then
torbypass=""
else
torbypass="-K curlcfg"
fi
if [ -n "${data}" ]; then if [ -n "${data}" ]; then
trace "[curl_it] curl -o webresponse-${rnd} -m 20 -w \"%{http_code}\" -H \"Content-Type: application/json\" -H \"X-Forwarded-Proto: https\" -d \"${data}\" -k ${url}" trace "[curl_it] curl ${torbypass} -o webresponse-${rnd} -m 20 -w \"%{http_code}\" -H \"Content-Type: application/json\" -H \"X-Forwarded-Proto: https\" -d \"${data}\" -k ${url}"
rc=$(curl -o webresponse-${rnd} -m 20 -w "%{http_code}" -H "Content-Type: application/json" -H "X-Forwarded-Proto: https" -d "${data}" -k ${url}) rc=$(curl ${torbypass} -o webresponse-${rnd} -m 20 -w "%{http_code}" -H "Content-Type: application/json" -H "X-Forwarded-Proto: https" -d "${data}" -k ${url})
returncode=$? returncode=$?
else else
trace "[curl_it] curl -o webresponse-$$ -m 20 -w \"%{http_code}\" -k ${url}" trace "[curl_it] curl ${torbypass} -o webresponse-$$ -m 20 -w \"%{http_code}\" -k ${url}"
rc=$(curl -o webresponse-${rnd} -m 20 -w "%{http_code}" -k ${url}) rc=$(curl ${torbypass} -o webresponse-${rnd} -m 20 -w "%{http_code}" -k ${url})
returncode=$? returncode=$?
fi fi
trace "[curl_it] HTTP return code=${rc}" trace "[curl_it] HTTP return code=${rc}"

View File

@@ -79,7 +79,8 @@ main() {
installation_info) installation_info)
# GET http://192.168.111.152:8080/info # GET http://192.168.111.152:8080/info
if [ -f "$DB_PATH/info.json" ]; then if [ -f "$DB_PATH/info.json" ]; then
response=$( cat "$DB_PATH/info.json" ) # 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 else
response='{ "error": "missing installation data" }' response='{ "error": "missing installation data" }'
fi fi