--- /dev/null
+#!/bin/bash
+
+# Obtain the hidden service name from a tor hidden service RSA key
+
+# Copyright (c) 2016 Peter Palfrader
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+set -e
+set -u
+set -o pipefail
+
+usage() {
+ echo "$0 [-p] [hidden service RSA key]"
+ echo " Computes the Tor onion hostname from a given RSA public or private key."
+ echo " Use -p to indicate you are passing a public key. If none is given as an"
+ echo " argument, one is read from stdin."
+}
+
+umask 077
+export LC_ALL=C
+
+if ! command -v openssl >/dev/null 2>&1 ; then
+ echo >&2 "This program needs the openssl command line tool".
+ exit 1
+fi
+
+tempdir=""
+cleanup() {
+ cd /
+ if [ -n "$tempdir" ]; then
+ rm -rf "$tempdir"
+ fi
+}
+trap 'cleanup' EXIT
+tempdir="$(mktemp -d)"
+
+PUBIN=""
+
+while getopts "ph" OPTION
+do
+ case $OPTION in
+ h)
+ usage
+ exit
+ ;;
+ p)
+ PUBIN=1
+ ;;
+ *)
+ usage >&2
+ exit 1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+if [ "$#" = 0 ]; then
+ KEY="$tempdir/key"
+ cat > "$KEY"
+elif [ "$#" = 1 ]; then
+ KEY="$1"
+ shift
+else
+ usage >&2
+ exit 1
+fi
+
+if [ -z "$PUBIN" ]; then
+ PKEY="$tempdir/pkey"
+ if ! openssl rsa -pubout < "$KEY" 2>&1 > "$PKEY" | (grep -Fxv 'writing RSA key' >&2 || true); then
+ echo >&2 "Maybe you need to use -p for using a public key?"
+ exit 1
+ fi
+ KEY="$PKEY"
+fi
+
+mod="$(openssl rsa -pubin < "$KEY" -modulus -noout | cut -d= -f 2)"
+exp="$(openssl rsa -pubin < "$KEY" -text -noout | awk '$1=="Exponent:" {print $2}')"
+cat > "$tempdir/asn" << EOF
+asn1=SEQUENCE:seq_sect
+[seq_sect]
+field1=INTEGER:0x$mod
+field2=INTEGER:$exp
+EOF
+
+openssl asn1parse -genconf "$tempdir/asn" -noout -out "$tempdir/blob"
+
+python -c 'import base64, hashlib, sys; \
+ d = hashlib.sha1(sys.stdin.read()).digest()[0:10]; \
+ print "%s.onion"%(base64.b32encode(d).lower(),)
+ ' < "$tempdir/blob"
+#if command -v base32 >/dev/null 2>&1 ; then
+# echo $(
+# perl -MDigest::SHA -e '
+# $/=undef;
+# $d=Digest::SHA::sha1(<>);
+# $d=substr($d,0,10);
+# print $d;
+# ' < "$tempdir/blob" | base32 | tr A-Z a-z
+# ).onion
+#else
+# perl -MDigest::SHA -e '
+# eval("use MIME::Base32 qw( RFC )");
+# if ($@) {
+# print STDERR "This program needs either the base32 command line tool or the MIME::Base32 perl module.\n";
+# exit 1;
+# }
+# $/=undef;
+# $d=Digest::SHA::sha1(<>);
+# $d=substr($d,0,10);
+# print lc(MIME::Base32::encode($d)), ".onion\n"
+# ' < "$tempdir/blob"
+#fi
+
+# vim:set et:
+# vim:set ts=4:
+# vim:set shiftwidth=4:
--- /dev/null
+class onion::balance {
+ include onion
+
+ package { 'onionbalance':
+ ensure => installed,
+ }
+ service { 'onionbalance':
+ ensure => running,
+ require => Package['onionbalance'],
+ }
+
+ file { '/usr/local/bin/tor-onion-name':
+ mode => '0555',
+ source => 'puppet:///modules/onion/tor-onion-name',
+ }
+
+ concat::fragment { 'onion::torrc_control_header':
+ target => "/etc/tor/torrc",
+ order => 10,
+ content => "ControlPort 9051\n\n",
+ }
+
+ concat { '/etc/onionbalance/config':
+ notify => Service['onionbalance'],
+ require => Package['onionbalance'],
+ }
+ concat::fragment { 'onion::balance::config_header':
+ target => "/etc/onionbalance/config",
+ order => 05,
+ content => "service:\n",
+ }
+}
--- /dev/null
+define onion::balance_service (
+) {
+ include onion::balance
+
+ $onion_hn = onionbalance_hostname($name)
+ if ! $onion_hn {
+ exec { "create-onionbalance-key-${name}":
+ command => "/bin/true && umask 0027 && openssl genrsa -out /etc/onionbalance/private_keys/${name}.key 1024 && chgrp onionbalance /etc/onionbalance/private_keys/${name}.key",
+ onlyif => "/bin/true && ! [ -e /etc/onionbalance/private_keys/${name}.key ]",
+ require => Package['onionbalance'],
+ }
+ }
+
+ concat::fragment { "onion::balance::service_header::${name}":
+ target => "/etc/onionbalance/config",
+ order => "50-${name}-10",
+ content => " - # ${name} via ${onion_hn}\n key: private_keys/${name}.key\n instances:\n",
+ }
+
+ Concat::Fragment <<| tag == "onion::balance::${name}" |>>
+}
concat::fragment { "onion::torrc_onionservice::${name}":
target => "/etc/tor/torrc",
- order => 10,
+ order => 50,
content => "HiddenServiceDir /var/lib/tor/onion/${name}\nHiddenServicePort ${port} ${target_address}:${target_port}\n\n",
}
if $onion_hn {
@@concat::fragment { "onion::balance::instance::$name::$hostname":
target => "/etc/onionbalance/config",
- content => " - address: ${onion_hn}\n name: ${hostname}-${name}",
- tag => "onion::balance::$name",
+ content => " - address: ${onion_hn}\n name: ${hostname}-${name}\n",
+ order => "50-${name}-20",
+ tag => "onion::balance::$name",
}
}
}