Files
hassio-addons/tor/rootfs/etc/s6-overlay/s6-rc.d/init-tor/run
Renat Gabdulhakov b6946ea5e2 [TOR] fix start up
2024-08-15 01:19:43 +00:00

237 lines
8.0 KiB
Plaintext
Executable File

#!/command/with-contenv bashio
# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: Tor
# Prepares the add-on for startup
# ==============================================================================
declare address
declare clientname
declare host
declare key
declare log_level
declare port
declare private_key
declare public_key
declare target_port
declare virtual_port
readonly torrc='/etc/tor/torrc'
readonly hidden_service_dir='/ssl/tor/hidden_service'
readonly authorized_clients_dir="${hidden_service_dir}/authorized_clients"
readonly clients_dir="${hidden_service_dir}/clients"
readonly hostname_file="${hidden_service_dir}/hostname"
# A hidden service without any ports is kinda useless
if bashio::config.true 'hidden_services' \
&& ! bashio::config.has_value 'ports'; then
bashio::log.fatal
bashio::log.fatal 'Add-on configuration is incomplete.'
bashio::log.fatal
bashio::log.fatal 'Hidden services where enabled, using the'
bashio::log.fatal '"hidden_services" add-on configuration option,'
bashio::log.fatal 'But the "port" option does not contain any values!'
bashio::log.fatal
bashio::log.fatal 'Please configure the "ports" option.'
bashio::exit.nok
fi
# Checks if client names where configured when using stealth mode
if bashio::config.true 'hidden_services' \
&& bashio::config.true 'stealth' \
&& ! bashio::config.has_value 'client_names';
then
bashio::log.fatal
bashio::log.fatal 'Add-on configuration is incomplete.'
bashio::log.fatal
bashio::log.fatal 'Stealth mode is enabled, using the "stealth" add-on'
bashio::log.fatal 'configuration option, but there are no client names'
bashio::log.fatal 'configured in the "client_names" add-on option.'
bashio::log.fatal
bashio::log.fatal 'Please configure the "client_names" option.'
bashio::exit.nok
fi
# Created needed directories
mkdir -p \
"${authorized_clients_dir}" \
"${clients_dir}" \
"${hidden_service_dir}" \
|| bashio::exit.nok 'Could not create tor data directories'
chmod -R 0700 /ssl/tor
# Find the matching Tor log level
if bashio::config.has_value 'log_level'; then
case "$(bashio::string.lower "$(bashio::config 'log_level')")" in
all|trace)
log_level="debug"
;;
debug)
log_level="info"
;;
info|notice)
log_level="notice"
;;
warning)
log_level="warn"
;;
error|fatal|off)
log_level="err"
;;
esac
echo "Log ${log_level} stdout" >> "${torrc}"
fi
# Configure Socks proxy
if bashio::config.true 'socks'; then
echo 'SOCKSPort 0.0.0.0:9050' >> "${torrc}"
else
echo 'SOCKSPort 127.0.0.1:9050' >> "${torrc}"
fi
# Configure hidden services
if bashio::config.true 'hidden_services'; then
echo "HiddenServiceDir ${hidden_service_dir}" >> "${torrc}"
for port in $(bashio::config 'ports'); do
count=$(echo "${port}" | sed 's/[^:]//g'| awk '{ print length }')
if [[ "${count}" == 0 ]]; then
host='homeassistant'
virtual_port="${port}"
target_port="${port}"
elif [[ "${count}" == 1 ]]; then
# Check if format is hostname/ip:port or port:port
first=$(echo "${port}" | cut -f1 -d:)
if [[ "${first}" =~ ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]) ]]; then
host='homeassistant'
virtual_port=$(echo "${port}" | cut -f1 -d:)
target_port=$(echo "${port}" | cut -f2 -d:)
else
host=$(echo "${port}" | cut -f1 -d:)
virtual_port=$(echo "${port}" | cut -f2 -d:)
target_port=$(echo "${port}" | cut -f2 -d:)
fi
elif [[ "${count}" == 2 ]]; then
host=$(echo "${port}" | cut -f1 -d:)
virtual_port=$(echo "${port}" | cut -f2 -d:)
target_port=$(echo "${port}" | cut -f3 -d:)
else
bashio::log.warning "$port Are not correct format, skipping..."
fi
if [[ "${count}" -le 2 ]]; then
echo "HiddenServicePort ${target_port} ${host}:${virtual_port}" \
>> "${torrc}"
fi
done
fi
# Configure bridges
if bashio::config.exists 'bridges' \
&& ! bashio::config.is_empty 'bridges';
then
bashio::log.info 'Use bridges:'
echo "UseBridges 1" >> "${torrc}"
# Add client for OBFS transport
echo "ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec /usr/local/bin/obfs4proxy managed" >> "${torrc}"
# Add client for Snowflake transport
echo "ClientTransportPlugin snowflake exec /usr/local/bin/snowflake" >> "${torrc}"
# Add client for WebTunnel transport
echo "ClientTransportPlugin webtunnel exec /usr/local/bin/webtunnel" >> "${torrc}"
# Add bridges
while read -r bridge; do
bashio::log.info "Bridge ${bridge}"
echo "Bridge ${bridge}" >> "${torrc}"
done <<< "$(bashio::config 'bridges')"
fi
# Figure out the address
if bashio::config.true 'hidden_services'; then
bashio::log.info 'Starting Tor temporarly...'
exec 3< <(tor)
until bashio::fs.file_exists "${hostname_file}"; do
bashio::log.info "Waiting for service to start..."
sleep 1
done
address=$(<"${hostname_file}")
grep -m 1 "Bootstrapped 100% (done): Done" <&3 >/dev/null 2>&1
kill "$(pgrep tor)" >/dev/null 2>&1
bashio::log.info '---------------------------------------------------------'
bashio::log.info 'Your Home Assistant instance is available on Tor!'
bashio::log.info "Address: ${address}"
bashio::log.info '---------------------------------------------------------'
fi
# Configure stealth mode
if bashio::config.true 'hidden_services' && bashio::config.true 'stealth';
then
# Following the documentation at:
# https://community.torproject.org/onion-services/advanced/client-auth/
while read -r clientname; do
# Generate key is they do not exist yet
if ! bashio::fs.file_exists "${authorized_clients_dir}/${clientname}.auth"
then
key=$(openssl genpkey -algorithm x25519)
private_key=$(
sed \
-e '/----.*PRIVATE KEY----\|^[[:space:]]*$/d' \
<<< "${key}" \
| base64 -d \
| tail -c 32 \
| base32 \
| sed 's/=//g'
)
public_key=$(
openssl pkey -pubout \
<<< "${key}" \
| sed -e '/----.*PUBLIC KEY----\|^[[:space:]]*$/d' \
| base64 -d \
| tail -c 32 \
| base32 \
| sed 's/=//g'
)
# Create authorized client file
echo "descriptor:x25519:${public_key}" \
> "${clients_dir}/${clientname}.auth"
echo "descriptor:x25519:${public_key}" \
> "${authorized_clients_dir}/${clientname}.auth"
# Create private key file
echo "${private_key}" \
> "${clients_dir}/${clientname}.key.txt"
echo "${address%.onion}:descriptor:x25519:${private_key}" \
> "${clients_dir}/${clientname}.auth_private"
bashio::log.red
bashio::log.red
bashio::log.red "Created keys for ${clientname}!"
bashio::log.red
bashio::log.red "Keys are stored in:"
bashio::log.red "${clients_dir}"
bashio::log.red
bashio::log.red "Public key":
bashio::log.red "${public_key}"
bashio::log.red
bashio::log.red "Private key:"
bashio::log.red "${private_key}"
bashio::log.red
bashio::log.red
else
bashio::log.info "Keys for ${clientname} already exists; skipping..."
fi
done <<< "$(bashio::config 'client_names')"
echo 'HiddenServiceAllowUnknownPorts 0' >> "${torrc}"
fi