123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- #!/usr/bin/env bash
- ################################################################################
- # #
- # hypertorify.sh #
- # #
- # version: alpha #
- # #
- # Hyperbola v0.4 - Transparent proxy through Tor #
- # #
- # Copyright (C) 2021 Sagar Acharya #
- # #
- # #
- # GNU GENERAL PUBLIC LICENSE #
- # #
- # This program is free software: you can redistribute it and/or modify #
- # it under the terms of the GNU General Public License as published by #
- # the Free Software Foundation, either version 3 of the License. #
- # #
- # 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 General Public License for more details. #
- # #
- # You should have received a copy of the GNU General Public License #
- # along with this program. If not, see <http://www.gnu.org/licenses/>. #
- ################################################################################
- ## General
- #
- # program information
- readonly prog_name="hypertorify"
- readonly version="alpha"
- readonly signature="Copyright (C) 2021 Sagar Acharya"
- readonly git_url="https://notabug.org/sagaracharya/hypertorify"
- # set colors for stdout
- export red="$(tput setaf 1)"
- export green="$(tput setaf 2)"
- export yellow="$(tput setaf 3)"
- export blue="$(tput setaf 4)"
- export magenta="$(tput setaf 5)"
- export cyan="$(tput setaf 6)"
- export white="$(tput setaf 7)"
- export b="$(tput bold)"
- export reset="$(tput sgr0)"
- ## Directories
- #
- readonly app_dir="/usr/share/hypertorify"
- ## Show program banner
- banner() {
- printf "${b}${cyan}
- _ _ __ __ _____ _______ ______ _______ _____ ______ _____ _______ __ __
- |_____| \_/ |_____] |______ |_____/ | | | |_____/ | |______ \_/
- | | | | |______ | \_ | |_____| | \_ __|__ | |
- v${version}
- =[ Transparent proxy through Tor
- ${reset}\\n\\n"
- }
- ## Print a message and exit with (1) when an error occurs
- die() {
- printf "${red}%s${reset}\\n" "[ERROR] ${@}" >&2
- exit 1
- }
- ## Print information
- info() {
- printf "${b}${cyan}%s${reset} ${b}%s${reset}\\n" "::" "${@}"
- }
- ## Print `OK` messages
- msg() {
- printf "${b}${green}%s${reset} %s\\n\\n" "[OK]" "${@}"
- }
- ## Check if the program run as a root
- check_root() {
- if [[ "${UID}" -ne 0 ]]; then
- die "Please run this program as a root!"
- fi
- }
- ## Display program version
- print_version() {
- printf "%s\\n" "${prog_name} ${version}"
- printf "%s\\n" "${signature}"
- printf "%s\\n" "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"
- printf "%s\\n" "This is free software: you are free to change and redistribute it."
- printf "%s\\n" "There is NO WARRANTY, to the extent permitted by law."
- exit 0
- }
- ## Check program settings
- #
- # - tor package
- # - tor configuration file: /etc/tor/torrc
- # - directory permissions: /var/lib/tor
- check_settings() {
- info "Check program settings"
- if ! hash tor 2>/dev/null; then
- die "tor isn't installed, exit"
- fi
- if [[ ! -d "${app_dir}/backups" ]]; then
- die "directory '${app_dir}/backups' not exist, run makefile first!"
- fi
- # check /var/lib/tor permissions
- #
- # required:
- # -rwx------ tor tor
- # (700)
- if [[ "$(stat -c '%U' /var/lib/tor)" != "tor" ]] &&
- [[ "$(stat -c '%a' /var/lib/tor)" != "700" ]]; then
- printf "%s\\n" "Set permissions of /var/lib/tor directory"
- chown -R tor:tor /var/lib/tor
- chmod -R 700 /var/lib/tor
- fi
- if [[ ! -f /etc/init.d/tor-hardened ]]; then
- die "Failed to find /etc/init.d/tor-hardened. Please install package tor-hardened-preferences."
- fi
- # check /etc/tor/torrc
- if [[ ! -f /etc/tor/torrc ]]; then
- die "/etc/tor/torrc file not exist, check Tor configuration"
- fi
- }
- ## nftables settings
- #
- # This function is used with args in start() & stop() for set/restore
- # nftables.
- #
- # Args:
- # tor_proxy -> set rules for Tor transparent proxy
- # default -> restore default nftables
- setup_nftables() {
- case "$1" in
- tor_proxy)
- printf "%s\\n" "Set nftables rules"
- ## flush current nftables rules
- #nft create table inet nat
- #nft create table inet filter
- #nft create chain inet filter input
- #nft add rule inet filter input accept
- #nft create chain inet filter forward
- #nft add rule inet filter forward accept
- #nft create chain inet filter output
- #nft add rule inet filter output accept
- # copy file /usr/share/hypertorify/data/nftables.rules in the
- # /etc/ directory
- if ! mv -f /etc/nftables.rules "${app_dir}/backups/nftables.rules.backup" 2>/dev/null; then
- die "can't backup file /etc/nftables.rules to hypertorify backup directory"
- fi
-
- if ! cp -f "${app_dir}/ruleset.nft" /etc/nftables.rules 2>/dev/null; then
- die "can't copy file /etc/nftables.rules"
- fi
- # set new nftables rules
-
- if nft -f < /etc/nftables.rules 2>/dev/null; then
- die "can't set nftables rules"
- fi
- # start nftables service
- if ! rc-service nftables start 2>/dev/null; then
- die "openrc error, exit!"
- fi
- ;;
- # restore default
- default)
- printf "%s\\n" "Restore default nftables"
- # flush nftables rules
- nft flush ruleset
-
- nft create table inet nat
- nft create table inet filter
- nft create chain inet filter input
- nft add rule inet filter input accept
- nft create chain inet filter forward
- nft add rule inet filter forward accept
- nft create chain inet filter output
- nft add rule inet filter output accept
- # rewrite default /etc/nftables.rules file
- if ! mv -f "${app_dir}/backups/nftables.rules.backup" /etc/nftables.rules 2>/dev/null; then
- die "can't restore backup nftables.rules.backup file from hypertorify backup directory"
- fi
- ;;
- esac
- }
- ## Check public IP address
- #
- # Make an HTTP request to the URL in the list, if the first request fails, try
- # with the next, then print the IP address.
- #
- # Thanks to "NotMilitaryAI" for this function
- check_ip() {
- info "Check public IP Address"
- local url_list=(
- 'https://ipleak.net/json/'
- 'https://api.myip.com/'
- )
- for url in "${url_list[@]}"; do
- local request="$(curl -s "$url")"
- local response="$?"
- if [[ "$response" -ne 0 ]]; then
- continue
- fi
- printf "%s\\n" "${request}"
- break
- done
- }
- ## Check status of program and services
- #
- # - tor-hardened
- # - tor settings (check if Tor works correctly)
- # - public IP address
- check_status() {
- info "Check current status of Tor service"
- if rc-service tor-hardened status | grep started >/dev/null 2>&1; then
- msg "Tor service is active"
- else
- die "Tor service is not running! exit"
- fi
- # make HTTP request with curl at: https://check.torproject.org/
- # and grep the necessary strings from the html page to test connection
- # with tor
- info "Check Tor network settings"
- # curl option details:
- # --socks5 <host[:port]> SOCKS5 proxy on given host + port
- # --socks5-hostname <host[:port]> SOCKS5 proxy, pass host name to proxy
- #
- # `-L` and `tac` for avoid error: "(23) Failed writing body"
- # https://github.com/kubernetes/helm/issues/2802
- # https://stackoverflow.com/questions/16703647/why-curl-return-and-error-23-failed-writing-body
- if curl -s -m 5 --socks5 "localhost:9050" --socks5-hostname "localhost:9050" -L "https://check.torproject.org/" \
- | cat | tac | grep -q 'Congratulations'; then
- printf "${b}${green}%s${reset} %s\\n\\n" \
- "[OK]" "Your system is configured to use Tor"
- else
- printf "${red}%s${reset}\\n\\n" "[!] Your system is not using Tor"
- printf "%s\\n" "try another Tor circuit with '${prog_name} --restart'"
- exit 1
- fi
- check_ip
- }
- ## Start transparent proxy through Tor
- start() {
- check_root
- # Exit if tor is already active
- if rc-service tor status | grep started >/dev/null 2>&1; then
- die "Tor service is already active, stop it first"
- fi
- banner
- sleep 2
- check_settings
- printf "\\n"
- info "Starting Transparent Proxy"
- # DNS settings: /etc/resolv.conf:
- #
- # write nameserver 127.0.0.1 to etc/resolv.conf file
- # i.e. use Tor DNSPort (see: /etc/tor/torrc)
- printf "%s\\n" "Configure DNS to use Tor's DNSPort"
- # backup current resolv.conf
- if ! cp /etc/resolv.conf "${app_dir}/backups/resolv.conf.backup"; then
- die "can't backup /etc/resolv.conf"
- fi
- # write new nameserver
- printf "%s\\n" "nameserver 127.0.0.1" > /etc/resolv.conf
- # restart tor-hardened
- printf "%s\\n" "Starting tor-hardened"
- if ! rc-service tor-hardened status | grep started >/dev/null 2>&1; then
- if ! rc-service tor-hardened start 2>/dev/null; then
- die "can't start tor-hardened, exit!"
- else
- echo "started tor-hardened"
- fi
- fi
- # nftables settings
- setup_nftables tor_proxy
- # check program status
- printf "\\n"
- check_status
- printf "\\n${b}${green}%s${reset} %s\\n" \
- "[OK]" "Transparent Proxy activated, your system is under Tor"
- }
- ## Stop transparent proxy
- #
- # stop connection with Tor Network and return to clearnet navigation
- stop() {
- check_root
- # don't run function if tor-hardened is NOT running!
- if rc-service tor-hardened status | grep started >/dev/null 2>&1; then
- info "Stopping Transparent Proxy"
- # restore default nftables and stop tor-hardened and nftables services
- setup_nftables default
-
- printf "%s\\n" "Stop Tor service"
- rc-service tor-hardened stop
- rc-service nftables stop
- # restore /etc/resolv.conf:
- #
- # restore file with resolvconf program if exists, otherwise copy the
- # original file from backup directory
- printf "%s\\n" "Restore default DNS"
- if hash resolvconf 2>/dev/null; then
- resolvconf -u
- else
- cp "${app_dir}/backups/resolv.conf.backup" /etc/resolv.conf
- fi
- # restore default /etc/tor/torrc
- printf "%s\\n" "Restore default /etc/tor/torrc"
- cp "${app_dir}/backups/torrc.backup" /etc/tor/torrc
- printf "\\n${b}${green}%s${reset} %s\\n" \
- "[-]" "Transparent Proxy stopped"
- exit 0
- else
- die "Tor-hardened service is not running! exit"
- fi
- }
- ## Restart
- #
- # restart tor-hardened (i.e. get new Tor exit node)
- # and change public IP address
- restart() {
- check_root
- if rc-service tor-hardened status | grep started >/dev/null 2>&1; then
- info "Change IP address"
- rc-service tor-hardened restart
- rc-service nftables restart
- sleep 1
- msg "IP address changed"
- check_ip
- exit 0
- else
- die "Tor service is not running! exit"
- fi
- }
- ## Show help menù
- usage() {
- printf "%s\\n" "${prog_name} ${version}"
- printf "%s\\n" "Hyperbola OS - Transparent proxy through Tor"
- printf "%s\\n\\n" "${signature}"
- printf "%s\\n\\n" "Usage: ${prog_name} [option]"
- printf "%s\\n\\n" "Options:"
- printf "%s\\n" "-h, --help show this help message and exit"
- printf "%s\\n" "-t, --tor start transparent proxy through tor"
- printf "%s\\n" "-c, --clearnet reset nftables and return to clearnet navigation"
- printf "%s\\n" "-s, --status check status of program and services"
- printf "%s\\n" "-i, --ipinfo show public IP address"
- printf "%s\\n" "-r, --restart restart tor service and change IP address"
- printf "%s\\n\\n" "-v, --version display program version and exit"
- printf "%s\\n" "Project URL: ${git_url}"
- printf "%s\\n" "Report bugs: ${git_url}/issues"
- exit 0
- }
- ## Main function
- #
- # parse command line arguments and start program
- main() {
- if [[ "$#" -eq 0 ]]; then
- printf "%s\\n" "${prog_name}: Argument required"
- printf "%s\\n" "Try '${prog_name} --help' for more information."
- exit 1
- fi
- while [[ "$#" -gt 0 ]]; do
- case "$1" in
- -t | --tor)
- start
- ;;
- -c | --clearnet)
- stop
- ;;
- -r | --restart)
- restart
- ;;
- -s | --status)
- check_status
- ;;
- -i | --ipinfo)
- check_ip
- ;;
- -v | --version)
- print_version
- ;;
- -h | --help)
- usage
- exit 0
- ;;
- -- | -* | *)
- printf "%s\\n" "${prog_name}: Invalid option '$1'"
- printf "%s\\n" "Try '${prog_name} --help' for more information."
- exit 1
- ;;
- esac
- exit 0
- done
- }
- # Call main
- main "${@}"
|