#!/bin/bash # # .---. . . # | | | # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-' # ' ' --' --' -' - -' ' ' -' -' -' ' - --' # # Freedom in the Cloud # # Onion functions # # License # ======= # # Copyright (C) 2014-2016 Bob Mottram # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . function add_email_hostname { extra_email_hostname="$1" email_hostnames=$(cat /etc/exim4/update-exim4.conf.conf | grep "dc_other_hostnames" | awk -F "'" '{print $2}') if [[ "$email_hostnames" != *"$extra_email_hostname"* ]]; then sed -i "s|dc_other_hostnames=.*|dc_other_hostnames='$emailhostnames;extra_email_hostname'|g" /etc/exim4/update-exim4.conf.conf update-exim4.conf dpkg-reconfigure --frontend noninteractive exim4-config systemctl restart saslauthd fi } function onion_update { # update so that new onion services appear systemctl reload tor } function onion_service_exists { onion_service_name="$1" if [ -f /var/lib/tor/hidden_service_${onion_service_name}/hostname ]; then echo "1" else echo "0" fi } function wait_for_onion_service_base { onion_service_name="$1" sleep_ctr=0 while [[ $(onion_service_exists ${onion_service_name}) == "0" ]]; do sleep 1 sleep_ctr=$((sleep_ctr + 1)) if [ $sleep_ctr -gt 10 ]; then break fi done } function wait_for_onion_service { onion_service_name="$1" wait_for_onion_service_base ${onion_service_name} if [[ $(onion_service_exists ${onion_service_name}) == "0" ]]; then # try a second time onion_update wait_for_onion_service_base ${onion_service_name} fi } function remove_onion_service { onion_service_name="$1" onion_service_port_to=$2 #sed -i "/stealth ${onion_service_name}/d" /etc/tor/torrc sed -i "/hidden_service_${onion_service_name}/d" /etc/tor/torrc sed -i "/hidden_service_${onion_service_name}_mobile/d" /etc/tor/torrc sed -i "/127.0.0.1:${onion_service_port_to}/d" /etc/tor/torrc if [ $3 ]; then sed -i "/127.0.0.1:${3}/d" /etc/tor/torrc if [ $4 ]; then sed -i "/127.0.0.1:${4}/d" /etc/tor/torrc if [ $5 ]; then sed -i "/127.0.0.1:${5}/d" /etc/tor/torrc fi fi fi if [ -d /var/lib/tor/hidden_service_${onion_service_name} ]; then shred -zu /var/lib/tor/hidden_service_${onion_service_name}/* rm -rf /var/lib/tor/hidden_service_${onion_service_name} fi if [ -d /var/lib/tor/hidden_service_${onion_service_name}_mobile ]; then shred -zu /var/lib/tor/hidden_service_${onion_service_name}_mobile/* rm -rf /var/lib/tor/hidden_service_${onion_service_name}_mobile fi remove_completion_param "${onion_service_name} onion domain" onion_update } function add_onion_service { onion_service_name="$1" onion_service_port_from=$2 onion_service_port_to=$3 if [[ $(onion_service_exists ${onion_service_name}) == "1" ]]; then echo $(cat /var/lib/tor/hidden_service_${onion_service_name}/hostname) return fi if [ ! -d /var/lib/tor ]; then echo $"No Tor installation found. ${onion_service_name} onion site cannot be configured." exit 877367 fi if ! grep -q "hidden_service_${onion_service_name}" /etc/tor/torrc; then echo "HiddenServiceDir /var/lib/tor/hidden_service_${onion_service_name}/" >> /etc/tor/torrc echo "HiddenServicePort ${onion_service_port_from} 127.0.0.1:${onion_service_port_to}" >> /etc/tor/torrc #echo "HiddenServiceAuthorizeClient stealth ${onion_service_name}" >> /etc/tor/torrc fi onion_update function_check wait_for_onion_service wait_for_onion_service ${onion_service_name} if [[ $(onion_service_exists ${onion_service_name}) == "0" ]]; then echo $"${onion_service_name} onion site hostname not found" exit 76362 fi onion_address=$(cat /var/lib/tor/hidden_service_${onion_service_name}/hostname) # Record the domain in the completion file set_completion_param "${onion_service_name} onion domain" "${onion_address}" echo $onion_address } function set_default_onion_domains { # If sites are only visible via Tor then for installation # purposes assign them some default domain names if [[ $ONION_ONLY == "no" ]]; then return fi POSTACTIV_DOMAIN_NAME='postactiv.local' GNUSOCIAL_DOMAIN_NAME='gnusocial.local' HTMLY_DOMAIN_NAME='htmly.local' GHOST_DOMAIN_NAME='ghost.local' DOKUWIKI_DOMAIN_NAME='dokuwiki.local' DEFAULT_DOMAIN_NAME="${PROJECT_NAME}.local" GIT_DOMAIN_NAME='gogs.local' } function create_avahi_onion_domains { if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi if [ ! -d /etc/avahi/services ]; then return fi if [ $GNUSOCIAL_DOMAIN_NAME ]; then function_check create_avahi_service create_avahi_service gnusocial http tcp $GNUSOCIAL_ONION_PORT fi if [ $HTMLY_DOMAIN_NAME ]; then function_check create_avahi_service create_avahi_service blog http tcp $HTMLY_ONION_PORT fi if [ $GIT_DOMAIN_NAME ]; then function_check create_avahi_service create_avahi_service git http tcp $GIT_ONION_PORT fi if [ $DOKUWIKI_DOMAIN_NAME ]; then function_check create_avahi_service create_avahi_service dokuwiki http tcp $DOKUWIKI_ONION_PORT fi } function allow_ssh_to_onion_address { if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi if [ ! -d /home/$MY_USERNAME/.ssh ]; then mkdir /home/$MY_USERNAME/.ssh fi if [ ! -d /etc/tor ]; then echo $'Tor not found when updating ssh' exit 528257 fi if ! grep -q "onion" /home/$MY_USERNAME/.ssh/config; then echo 'Host *.onion' >> /home/$MY_USERNAME/.ssh/config echo 'ProxyCommand connect -R remote -5 -S 127.0.0.1:9050 %h %p' >> /home/$MY_USERNAME/.ssh/config fi } function enable_ssh_via_onion { if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi apt-get -yq install tor connect-proxy if ! grep -q 'Host *.onion' /home/$MY_USERNAME/.ssh/config; then if [ ! -d /home/$MY_USERNAME/.ssh ]; then mkdir /home/$MY_USERNAME/.ssh fi echo 'Host *.onion' >> /home/$MY_USERNAME/.ssh/config echo 'ProxyCommand connect -R remote -5 -S 127.0.0.1:9050 %h %p' >> /home/$MY_USERNAME/.ssh/config chown $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.ssh chown $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.ssh/config fi if ! grep -q 'Host *.onion' /root/.ssh/config; then if [ ! -d /root/.ssh ]; then mkdir /root/.ssh fi echo 'Host *.onion' >> /root/.ssh/config echo 'ProxyCommand connect -R remote -5 -S 127.0.0.1:9050 %h %p' >> /root/.ssh/config fi mark_completed $FUNCNAME } function configure_ssh_onion { if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi SSH_ONION_HOSTNAME=$(add_onion_service ssh ${SSH_PORT} ${SSH_PORT}) set_completion_param "ssh onion domain" "${SSH_ONION_HOSTNAME}" add_email_hostname "${SSH_ONION_HOSTNAME}" mark_completed $FUNCNAME } function install_tor { if [[ $SYSTEM_TYPE == "mesh*" ]]; then return fi if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi apt-get -yq install tor if [ ! -f /etc/tor/torrc ]; then echo 'Tor failed to install' exit 38259 fi # turn off logging sed -i 's|#Log notice file.*|Log notice file /dev/null|g' /etc/tor/torrc sed -i 's|Log notice file.*|Log notice file /dev/null|g' /etc/tor/torrc mark_completed $FUNCNAME } function resolve_dns_via_tor { if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi if [ ! -f /etc/tor/torrc ]; then echo $'tor was not installed' exit 52952 fi # resolve DNS via tor if ! grep 'DNSPort 53' /etc/tor/torrc; then echo 'DNSPort 53' >> /etc/tor/torrc echo 'AutomapHostsOnResolve 1' >> /etc/tor/torrc echo 'AutomapHostsSuffixes .exit,.onion' >> /etc/tor/torrc onion_update fi # don't change resolv.conf sed -i 's|, domain-name-servers||g' /etc/dhcp/dhclient.conf # point resolv.conf to tor echo 'nameserver 127.0.0.1:53' > /etc/resolv.conf # prevent resolv.conf from changing chattr +i /etc/resolv.conf mark_completed $FUNCNAME } # see https://trac.torproject.org/projects/tor/wiki/doc/TransparentProxy # Local Redirection and Anonymizing Middlebox function route_outgoing_traffic_through_tor { if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi if [[ $ROUTE_THROUGH_TOR != "yes" ]]; then return fi apt-get -yq install tor tor-arm ### set variables # Destinations you don't want routed through Tor _non_tor="192.168.1.0/24 192.168.0.0/24" # The user that Tor runs as _tor_uid="debian-tor" # Tor's TransPort _trans_port="9040" # Your internal interface _int_if="eth0" ### Set iptables *nat iptables -t nat -A OUTPUT -o lo -j RETURN iptables -t nat -A OUTPUT -m owner --uid-owner $_tor_uid -j RETURN iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53 # Allow clearnet access for hosts in $_non_tor for _clearnet in $_non_tor; do iptables -t nat -A OUTPUT -d $_clearnet -j RETURN iptables -t nat -A PREROUTING -i $_int_if -d $_clearnet -j RETURN done # Redirect all other pre-routing and output to Tor iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports $_trans_port iptables -t nat -A PREROUTING -i $_int_if -p udp --dport 53 -j REDIRECT --to-ports 53 iptables -t nat -A PREROUTING -i $_int_if -p tcp --syn -j REDIRECT --to-ports $_trans_port ### set iptables *filter iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow clearnet access for hosts in $_non_tor for _clearnet in $_non_tor 127.0.0.0/8; do iptables -A OUTPUT -d $_clearnet -j ACCEPT done # Allow only Tor output iptables -A OUTPUT -m owner --uid-owner $_tor_uid -j ACCEPT iptables -A OUTPUT -j REJECT function_check save_firewall_settings save_firewall_settings if ! grep -q "fs.file-max" /etc/sysctl.conf; then echo "fs.file-max=100000" >> /etc/sysctl.conf /sbin/sysctl -p -q fi echo 'domain localdomain' > /etc/resolv.conf echo 'search localdomain' >> /etc/resolv.conf echo 'nameserver 127.0.0.1' >> /etc/resolv.conf if ! grep -q "VirtualAddrNetworkIPv4" /etc/tor/torrc; then echo 'VirtualAddrNetworkIPv4 10.192.0.0/10' >> /etc/tor/torrc fi if ! grep -q "AutomapHostsOnResolve" /etc/tor/torrc; then echo 'AutomapHostsOnResolve 1' >> /etc/tor/torrc fi if ! grep -q "TransPort" /etc/tor/torrc; then echo 'TransPort 9040' >> /etc/tor/torrc fi if ! grep -q "TransListenAddress 127.0.0.1" /etc/tor/torrc; then echo 'TransListenAddress 127.0.0.1' >> /etc/tor/torrc fi if ! grep -q "TransListenAddress $LOCAL_NETWORK_STATIC_IP_ADDRESS" /etc/tor/torrc; then echo "TransListenAddress $LOCAL_NETWORK_STATIC_IP_ADDRESS" >> /etc/tor/torrc fi if ! grep -q "DNSPort" /etc/tor/torrc; then echo 'DNSPort 53' >> /etc/tor/torrc fi if ! grep -q "DNSListenAddress 127.0.0.1" /etc/tor/torrc; then echo 'DNSListenAddress 127.0.0.1' >> /etc/tor/torrc fi if ! grep -q "DNSListenAddress $LOCAL_NETWORK_STATIC_IP_ADDRESS" /etc/tor/torrc; then echo "DNSListenAddress $LOCAL_NETWORK_STATIC_IP_ADDRESS" >> /etc/tor/torrc fi mark_completed $FUNCNAME } function get_app_onion_address { app_name="$1" mobilestr="$2" if [ ${#mobilestr} -gt 0 ]; then mobilestr="_${mobilestr}" fi if grep -q "${app_name}${mobilestr} onion domain" $COMPLETION_FILE; then if grep -q "${app_name}${mobilestr} onion domain" $COMPLETION_FILE; then echo $(cat ${COMPLETION_FILE} | grep "${app_name}${mobilestr} onion domain" | head -n 1 | awk -F ':' '{print $2}') return fi fi echo "" } function tor_add_bridge { bridge_ip_address="$1" bridge_port="$2" bridge_key="$3" bridge_type='obfs4' if [[ "$bridge_ip_address" != *"."* ]]; then return fi if [ ${#bridge_port} -eq 0 ]; then return fi if [ ${#bridge_key} -eq 0 ]; then return fi apt-get -yq install obfs4proxy if grep -q "ClientTransportPlugin" /etc/tor/torrc; then sed -i 's|#ClientTransportPlugin|ClientTransportPlugin|g' /etc/tor/torrc sed -i 's|# ClientTransportPlugin|ClientTransportPlugin|g' /etc/tor/torrc sed -i 's|ClientTransportPlugin.*|ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy managed|g' /etc/tor/torrc else echo 'ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy managed' >> /etc/tor/torrc fi if grep -q "UseBridges" /etc/tor/torrc; then sed -i 's|#UseBridges|UseBridges|g' /etc/tor/torrc sed -i 's|# UseBridges|UseBridges|g' /etc/tor/torrc sed -i 's|UseBridges.*|UseBridges 1|g' /etc/tor/torrc else echo 'UseBridges 1' >> /etc/tor/torrc fi bridge_str="Bridge $bridge_type ${bridge_ip_address}:${bridge_port} ${bridge_key}" if ! grep -q "${bridge_str}" /etc/tor/torrc; then sed -i "/UseBridges/a ${bridge_str}" >> /etc/tor/torrc fi systemctl restart tor } function tor_remove_bridge { bridge_ip_address="$1" bridge_type='obfs4' if [[ "$bridge_ip_address" == *"."* ]]; then bridge_str="Bridge $bridge_type ${bridge_ip_address}" else if grep -q " ${bridge_ip_address}" /etc/tor/torrc; then bridge_str=" ${bridge_ip_address}" else return fi fi if grep -q "${bridge_str}" /etc/tor/torrc; then sed -i "/${bridge_str}/d" /etc/tor/torrc fi # If there are no bridges remaining then remove UseBridges if ! grep -q "Bridge " /etc/tor/torrc; then if ! grep -q "#UseBridges" /etc/tor/torrc; then sed -i 's|UseBridges|#UseBridges|g' /etc/tor/torrc fi if ! grep -q "#ClientTransportPlugin" /etc/tor/torrc; then sed -i 's|ClientTransportPlugin|#ClientTransportPlugin|g' /etc/tor/torrc fi fi systemctl restart tor } function tor_create_bridge_relay { read_config_param 'TOR_BRIDGE_PORT' read_config_param 'TOR_BRIDGE_NICKNAME' if [ ! $TOR_BRIDGE_PORT ]; then return fi if [ ${#TOR_BRIDGE_PORT} -eq 0 ]; then return fi if [ ${#TOR_BRIDGE_NICKNAME} -eq 0 ]; then return fi apt-get -yq install obfs4proxy sed -i 's|#BridgeRelay.*|BridgeRelay 1|g' /etc/tor/torrc sed -i 's|BridgeRelay.*|BridgeRelay 1|g' /etc/tor/torrc sed -i 's|#ServerTransportPlugin.*|ServerTransportPlugin obfs4 exec /usr/bin/obfs4proxy|g' /etc/tor/torrc sed -i 's|ServerTransportPlugin.*|ServerTransportPlugin obfs4 exec /usr/bin/obfs4proxy|g' /etc/tor/torrc if ! grep -q 'ExtORPort ' /etc/tor/torrc; then echo "ExtORPort $TOR_BRIDGE_PORT" >> /etc/tor/torrc else sed -i "s|#ExtORPort .*|ExtORPort $TOR_BRIDGE_PORT|g" /etc/tor/torrc sed -i "s|ExtORPort .*|ExtORPort $TOR_BRIDGE_PORT|g" /etc/tor/torrc fi read_config_param 'MY_EMAIL_ADDRESS' sed -i "s|#ContactInfo.*|ContactInfo $MY_EMAIL_ADDRESS|g" /etc/tor/torrc if [ $TOR_BRIDGE_NICKNAME ]; then sed -i "s|#Nickname.*|Nickname $TOR_BRIDGE_NICKNAME|g" /etc/tor/torrc sed -i "s|Nickname.*|Nickname $TOR_BRIDGE_NICKNAME|g" /etc/tor/torrc fi firewall_add tor_bridge $TOR_BRIDGE_PORT tcp systemctl restart tor } function tor_remove_bridge_relay { if ! grep -q '#BridgeRelay ' /etc/tor/torrc; then sed -i 's|BridgeRelay |#BridgeRelay |g' /etc/tor/torrc fi if ! grep -q '#ServerTransportPlugin ' /etc/tor/torrc; then sed -i 's|ServerTransportPlugin |#ServerTransportPlugin |g' /etc/tor/torrc fi if ! grep -q '#ExtORPort ' /etc/tor/torrc; then sed -i 's|ExtORPort |#ExtORPort |g' /etc/tor/torrc fi if ! grep -q '#ContactInfo ' /etc/tor/torrc; then sed -i "s|ContactInfo |#ContactInfo |g" /etc/tor/torrc fi if ! grep -q '#Nickname ' /etc/tor/torrc; then sed -i "s|Nickname |#Nickname |g" /etc/tor/torrc fi read_config_param 'TOR_BRIDGE_PORT' firewall_remove $TOR_BRIDGE_PORT tcp systemctl restart tor } # NOTE: deliberately no exit 0