diff --git a/net/tor-hs/Makefile b/net/tor-hs/Makefile new file mode 100644 index 0000000000..3a5490a580 --- /dev/null +++ b/net/tor-hs/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 02020 CZ.NIC, z. s. p. o. (https://www.nic.cz/) +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=tor-hs +PKG_VERSION:=0.0.1 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Jan Pavlinec +PKG_LICENSE:=GPL-3.0-or-later + +include $(INCLUDE_DIR)/package.mk + +define Package/tor-hs + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + TITLE:=Tor hidden service configurator + DEPENDS:=+tor +endef + +define Package/tor-hs/description + Tor Hidden Service configurator +endef + +define Package/tor-hs/conffiles +/etc/config/tor-hs +endef + +define Build/Compile +endef + +define Build/Install +endef + +define Package/tor-hs/install + $(INSTALL_DIR) $(1)/etc/config/ + $(CP) ./files/tor-hs.conf $(1)/etc/config/tor-hs + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) ./files/tor-hs.init $(1)/etc/init.d/tor-hs + $(INSTALL_DIR) $(1)/etc/tor/ + $(INSTALL_BIN) ./files/nextcloud-update.sh $(1)/etc/tor/ + $(INSTALL_DIR) $(1)/usr/libexec/rpcd + $(INSTALL_BIN) ./files/tor_rpcd.sh $(1)/usr/libexec/rpcd/ +endef + +$(eval $(call BuildPackage,tor-hs)) diff --git a/net/tor-hs/README.md b/net/tor-hs/README.md new file mode 100644 index 0000000000..649ff31f62 --- /dev/null +++ b/net/tor-hs/README.md @@ -0,0 +1,104 @@ +# Tor Hidden service configurator +**tor-hs** packages tries to simplify creating of hidden services on OpenWrt routers. + +## Requirements +To run **tor-hs**, you need Tor package with uci config support (it was added +with [this commit](https://github.com/openwrt/packages/commit/ca6528f002d74445e3d0a336aeb9074fc337307a) ). + +## Instalation +To install package simple run +``` +opkg update +opkg install tor-hs +``` + +## Configuration +Uci configuration is located in **/etc/config/tor-hs** + +### Required section of configuration +There is one required section **common** + +Example of this section +``` +config tor-hs common + option GenConf "/etc/tor/torrc_hs" + option HSDir "/etc/tor/hidden_service" + option RestartTor "true" + option UpdateTorConf "true" +``` + +#### Table with options description +| Type | Name | Default | Description | +| ------ | ------ | ------ | ------ | +| option |GenConf | /etc/tor/torrc_generated|Generated config by tor-hs.| +| option | HSDir |/etc/tor/hidden_service|Directory with meta-data for hidden services (hostname,keys,etc).| +| option | RestartTor | true| It will restart tor after running **/etc/init.d/tor-hs start**.| +| option | UpdateTorConf | true|Update /etc/config/tor with config from **GenConf** option.| + +### Hidden service configuration +If you want to create a new hidden service, you have to add a hidden-service section. For every hidden service, there should be a new **hidden-service** section. + +Example of hidden service section for ssh server: + +``` +config hidden-service + option Name 'sshd' + option Description "Hidden service for ssh" + option Enabled 'false' + option IPv4 '127.0.0.1' + #public port=2222, local port=22 + list PublicLocalPort '2222;22' +``` + +#### Table with options description + +| Type | Name | Example value | Description | +| ------ | ------ | ------ | ------ | +| option | Name | sshd| Name of hidden service. It is used as directory name in **HSDir**| +| option | Description| Hidden service for ssh| Description used in **rpcd** service| +| option | Enabled |false| Enable hidden service after running **tor-hs** init script| +| option |IPv4 |127.0.0.1|Local IPv4 address of service. Service could run on another device, in that case OpenWrt will redirect comunication. | +| list | PublicLocalPort| 2222;22| Public port is port accesible via Tor network. Local port is normal port of service.| +|option| HookScript |'/etc/tor/nextcloud-update.php'| Path to script which is executed after starting tor-hs. Script is executed with paramters **--update-onion** **hostname** . Hostname is replaced with Onion v3 address for given hidden service. + +## Running service + +To enable tor-hs service run +``` +/etc/init.d/tor-hs enable +/etc/init.d/tor-hs start + +``` +In case you enabled option *RestartTor* and *UpdateTorConf* hidden service should be running. +Otherwise, you should also restart tor daemon. + +``` +/etc/init.d/tor restart +``` + +After that you should also restart rpcd daemon, so you can use tor-hs RPCD service. +``` +/etc/init.d/rpcd restart +``` + +### RPCD + +RPCD servis helps users to access basic informations about hidden services on router. After running HS it contains onion url for given hidden service in hostname value. +``` +root@turris:/# ubus call tor_rpcd.sh list-hs '{}' +{ + "hs-list": [ + { + "name": "sshd", + "description": "Hidden service for ssh", + "enabled": "1", + "ipv4": "127.0.0.1", + "hostname": "****hidden-service-hostname****.onion", + "ports": [ + "22;22" + ] + } + ] +} +``` + diff --git a/net/tor-hs/files/nextcloud-update.sh b/net/tor-hs/files/nextcloud-update.sh new file mode 100755 index 0000000000..3c485e8639 --- /dev/null +++ b/net/tor-hs/files/nextcloud-update.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# This is example script for tor-hs uci config +# HookScript option. Script is then called after running +# hidden service. +# It disables trusted domain check for nextcloud. + +NEXTCLOUD_CLI_SCRIPT="/srv/www/nextcloud/occ" + +nextcloud_cli() { + sudo -u nobody php-cli "$NEXTCLOUD_CLI_SCRIPT" "$@" +} + + +nextcloud_add_domain() { + onion="$1" + if [ -n "$onion" ] && nextcloud_cli config:system:get trusted_domains |grep "$onion" ; then + echo "Info: Trusted domains already disabled. Nothing to do." >&2 + else + echo "Info: Disabling trusted domains." >&2 + nextcloud_cli config:system:set trusted_domains 1000 --value=$onion + fi +} + +print_help() { + echo "Help" +} + +# Check occ command +[ -f "$NEXTCLOUD_CLI_SCRIPT" ] || { + echo "Error: occ command not found!" >&2 + exit 1 +} + +################################################################ + +case "$1" in +--update-onion) + nextcloud_add_domain "$2" +;; + +*) + print_help +;; +esac diff --git a/net/tor-hs/files/tor-hs.conf b/net/tor-hs/files/tor-hs.conf new file mode 100644 index 0000000000..5480685d0f --- /dev/null +++ b/net/tor-hs/files/tor-hs.conf @@ -0,0 +1,22 @@ +config tor-hs common + #option GenConf "/etc/tor/torrc_hs" + option GenConf "/etc/tor/torrc_generated" + option HSDir "/etc/tor/hidden_service" + option RestartTor "true" + option UpdateTorConf "true" + +#config hidden-service +# option Name 'sshd' +# option Description "Hidden service for ssh" +# option Enabled 'false' +# option IPv4 '127.0.0.1' +# #public port=2222, local port=22 +# list PublicLocalPort '2222;22' + +#config hidden-service +# option Name 'nextcloud' +# option Description "Hidden service for Nextcloud" +# option Enabled 'false' +# option IPv4 '127.0.0.1' +# option HookScript '/etc/tor/nextcloud-update.sh' +# list PublicLocalPort '80;80' diff --git a/net/tor-hs/files/tor-hs.init b/net/tor-hs/files/tor-hs.init new file mode 100755 index 0000000000..aab531b1ca --- /dev/null +++ b/net/tor-hs/files/tor-hs.init @@ -0,0 +1,116 @@ +#!/bin/sh /etc/rc.common + +START=52 +STOP=52 + +USE_PROCD=1 + +TORRC_FILE=/etc/tor/torrc_generated # file with torrc config +HS_DIR_PATH=/etc/tor/hidden_service #hidden service directory path +TOR_USER=tor + +clean_hs() { + local name="" +} + +config_tor() { + local restart_tor update_config + config_get_bool restart_tor "common" RestartTor + config_get_bool update_config "common" UpdateTorConf + + tail_conf=$(uci show tor.conf.tail_include 2>/dev/null) + head_conf=$(uci show tor.conf.head_include 2>/dev/null) + echo "tail_conf $tail_conf" + + if [ "$update_config" = "1" ]; then + if [ -n "$(echo $tail_conf | grep $TORRC_FILE)" ] || [ -n "$(echo $head_conf | grep $TORRC_FILE)" ]; then + echo "Info. Not updating tor configuration" + else + #uci add_list + echo "Info. Updating tor configuration" + uci add_list tor.conf.tail_include="$TORRC_FILE" + uci commit tor + fi + fi + + if [ "$restart_tor" = "1" ]; then + /etc/init.d/tor restart + fi +} + +handle_hs_ports_conf() { + local public_port local_port + local value="$1" + local ipv4="$2" + local name="$3" + + public_port=$(echo "$value"|awk -F';' '{print $1}') + local_port=$(echo "$value"|awk -F';' '{print $2}') + echo "HiddenServicePort $public_port $ipv4:$local_port">>$TORRC_FILE +} + +parse_hs_conf() { + local name public_port local_port enable_hs ipv4 + local config="$1" + + config_get name "$config" Name + config_get description "$config" Description + + config_get_bool enable_hs "$config" Enabled 0 + config_get ipv4 "$config" IPv4 + + if [ "$enable_hs" = "1" ]; then + mkdir -p "$HS_DIR_PATH/$name" + chown "$TOR_USER":"$TOR_USER" "$HS_DIR_PATH/" + chown "$TOR_USER:$TOR_USER" "$HS_DIR_PATH/$name" + chmod 700 "$HS_DIR_PATH/" + chmod 700 "$HS_DIR_PATH/$name/" + + echo "HiddenServiceDir $HS_DIR_PATH/$name" >>$TORRC_FILE + config_list_foreach "$config" PublicLocalPort handle_hs_ports_conf "$ipv4" "$name" + fi +} + +parse_hs_conf_hooks() { + local name hook_script enable_hs hostname_file + local config="$1" + + config_get enable_hs "$config" Enabled 0 + config_get hook_script "$config" HookScript + config_get name "$config" Name + + hostname="$HS_DIR_PATH/$name/hostname" + + # check if we should run hook_script + if [ "$enable_hs" = "true" ] && [ -x "$hook_script" ] && [ -f "$hostname" ] ; then + hostname_uri=$(cat "$hostname") + # call hook script + $hook_script "--update-onion" "$hostname_uri" + fi +} + +parse_common_conf() { + local hs_dir generated_config + config_get generated_config "common" GenConf + config_get hs_dir "common" HSDir + [ -n "$hs_dir" ] && HS_DIR_PATH="$hs_dir" + [ -n "$generated_config" ] && TORRC_FILE="$generated_config" +} + +start_service() { + config_load tor-hs + # clean config + echo "" > $TORRC_FILE # clean config + + # load common config + parse_common_conf + + # load hs service + config_foreach parse_hs_conf hidden-service + + # update tor config + config_tor + + # load and run tor-hs hooks + config_foreach parse_hs_conf_hooks hidden-service +} diff --git a/net/tor-hs/files/tor_rpcd.sh b/net/tor-hs/files/tor_rpcd.sh new file mode 100755 index 0000000000..bfcd788017 --- /dev/null +++ b/net/tor-hs/files/tor_rpcd.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +. /lib/functions.sh + +get_onion_hostname() { + local name="$1" + config_get hs_dir common HSDir + if [ -f "$hs_dir/$name/hostname" ]; then + cat "$hs_dir/$name/hostname" + fi +} + +get_port_list() { + local config="$1" + config_get ports "$config" PublicLocalPort + tmp="$(echo $ports |sed "s| |','|g")" + echo -ne "['$tmp']" +} + +parse_hs_conf() { + local name description public_port local_port enable_bool public_local_port ipv4 + local config="$1" + local custom="$2" + + config_get name "$config" Name + config_get description "$config" Description + + config_get_bool enable_hs "$config" Enabled 0 + config_get ipv4 "$config" IPv4 + + hostname="$(get_onion_hostname $name)" + port_list="$(get_port_list $config)" + echo "{" + echo \"name\":\"$name\", + echo \"description\":\"$description\", + echo \"enabled\":\"$enable_hs\", + echo \"ipv4\":\"$ipv4\", + echo \"hostname\":\"$hostname\", + echo \"ports\":$port_list + echo "}," +} + +get_tor_hs_list() { + config_load tor-hs + echo "{" + echo '"hs-list":[' + config_foreach parse_hs_conf hidden-service + echo "]" + echo "}" +} + + + +case "$1" in + list) + echo '{ "list-hs": { } }' + ;; + call) + case "$2" in + list-hs) + # return json object + get_tor_hs_list + ;; + esac + ;; +esac + + +