forked from EvergreenCrypto/docker-finance
Merge pull request #118 into master
5e59087client: docker.bash: add Tor plugin to usage help (Aaron Fiore)c475dbdclient: manifest: add `proxychains-ng` package (Aaron Fiore)77a8b21container: lib_fetch: implement Tor support (Aaron Fiore)5b4bf6fclient: plugins: implement Tor plugin (tor.bash) (Aaron Fiore)59d11b4client: Dockerfiles: add `proxychains-ng` package (Aaron Fiore)
This commit is contained in:
@@ -63,6 +63,7 @@ USER root
|
||||
RUN pacman -Syu \
|
||||
bc \
|
||||
composer \
|
||||
proxychains-ng \
|
||||
--noconfirm --disable-download-timeout
|
||||
|
||||
RUN sed -i \
|
||||
|
||||
@@ -73,7 +73,8 @@ RUN apt-get install -y \
|
||||
php \
|
||||
php-bcmath \
|
||||
php-curl \
|
||||
php-gmp
|
||||
php-gmp \
|
||||
proxychains4
|
||||
|
||||
USER builder
|
||||
WORKDIR /usr/local/lib/php
|
||||
|
||||
@@ -42,6 +42,7 @@ container:
|
||||
- "hledger-iadd"
|
||||
- "hledger-ui"
|
||||
- "hledger-web"
|
||||
- "proxychains-ng"
|
||||
- "python-pipx"
|
||||
- "stack"
|
||||
- "timew"
|
||||
@@ -90,6 +91,7 @@ container:
|
||||
- "hledger-ui"
|
||||
- "hledger-web"
|
||||
- "pipx"
|
||||
- "proxychains4"
|
||||
- "timewarrior"
|
||||
- "vim"
|
||||
- "visidata"
|
||||
|
||||
161
client/plugins/docker/tor.bash
Executable file
161
client/plugins/docker/tor.bash
Executable file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# docker-finance | modern accounting for the power-user
|
||||
#
|
||||
# Copyright (C) 2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
#
|
||||
# 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, 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 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# "Libraries"
|
||||
#
|
||||
|
||||
[ -z "$DOCKER_FINANCE_CLIENT_REPO" ] && exit 1
|
||||
source "${DOCKER_FINANCE_CLIENT_REPO}/client/src/docker/lib/lib_docker.bash"
|
||||
|
||||
[[ -z "$global_platform" || -z "$global_arg_delim_1" || -z "$global_user" || -z "$global_tag" ]] && lib_utils::die_fatal
|
||||
instance="${global_platform}${global_arg_delim_1}${global_user}:${global_tag}"
|
||||
lib_docker::docker "$instance" # NOTE: "constructor" only needed if calling library directly
|
||||
|
||||
#
|
||||
# Implementation
|
||||
#
|
||||
|
||||
declare -g tor_container="docker-finance_tor"
|
||||
|
||||
# TODO: current implementation will clobber any other proxychains usage (i.e., other SOCKS proxy or overlay network (I2P, etc.))
|
||||
function tor::start()
|
||||
{
|
||||
[[ -z "$global_container" || -z "$global_network" ]] && lib_utils::die_fatal
|
||||
|
||||
# NOTE: proxychains.conf's [ProxyList] won't allow hostnames (or Docker network container name).
|
||||
# So, to avoid conflicting IP address spaces, docker-finance will not hardcode address space.
|
||||
# Ergo, a already-running container will be needed (sorry, lib_docker::run())
|
||||
if ! docker container inspect -f '{{.State.Running}}' "$global_container" &>/dev/null; then
|
||||
lib_utils::die_fatal "docker-finance not running! Bring \`up\` container and try again."
|
||||
fi
|
||||
|
||||
local -r _torrc="/etc/tor/torrc"
|
||||
|
||||
if docker container inspect -f '{{.State.Running}}' "$tor_container" &>/dev/null; then
|
||||
lib_utils::print_error "${tor_container}: instance already running (consider \`restart\`)"
|
||||
return 1
|
||||
else
|
||||
docker run -it --rm --detach \
|
||||
--network "$global_network" \
|
||||
--name="${tor_container}" \
|
||||
--entrypoint=/bin/sh alpine:latest -c "
|
||||
apk update \
|
||||
&& apk add tor \
|
||||
&& cp ${_torrc}.sample ${_torrc} \
|
||||
&& su -s /usr/bin/tor tor" 1>/dev/null || lib_utils::die_fatal
|
||||
fi && lib_utils::print_info "${tor_container}: container started"
|
||||
|
||||
# Get Tor container's local IP
|
||||
local _ip
|
||||
_ip="$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $tor_container)"
|
||||
lib_utils::print_info "${tor_container}: container IP '${_ip}'"
|
||||
|
||||
# Need to wait for a working installation
|
||||
lib_utils::print_warning "${tor_container}: waiting for Tor installation"
|
||||
while ! docker exec "$tor_container" /bin/sh -c 'apk info -e tor' 1>/dev/null; do
|
||||
sleep 1s
|
||||
done && lib_utils::print_info "${tor_container}: Tor installation ready"
|
||||
|
||||
# Update torrc with container's local IP (to avoid 0.0.0.0)
|
||||
lib_utils::print_info "${tor_container}: updating $_torrc"
|
||||
docker exec "$tor_container" \
|
||||
/bin/sh -c "
|
||||
sed -i '/^SOCKSPort /d' ${_torrc} \
|
||||
&& echo 'SOCKSPort ${_ip}:9050' >>${_torrc}" || lib_utils::die_fatal
|
||||
|
||||
# Have Tor pickup changes
|
||||
lib_utils::print_info "${tor_container}: restarting Tor with updated ${_torrc}"
|
||||
docker exec "$tor_container" /bin/sh -c "pkill -HUP tor" || lib_utils::die_fatal
|
||||
|
||||
# Set docker-finance's proxychains to point to Tor instance
|
||||
local -r _proxychains="/etc/proxychains.conf"
|
||||
lib_utils::print_info "${global_container}: updating $_proxychains"
|
||||
docker exec -it --user root "$global_container" \
|
||||
/bin/bash -i -c "
|
||||
sed -i \
|
||||
-e 's:^#quiet_mode:quiet_mode:' \
|
||||
-e 's:^# localnet 127.0.0.0/255.0.0.0:localnet 127.0.0.0/255.0.0.0:' \
|
||||
-e '/^socks/d' $_proxychains \
|
||||
&& echo 'socks5 $_ip 9050' >>$_proxychains" || lib_utils::die_fatal
|
||||
|
||||
# Test Tor connection
|
||||
local -r _sleep="15s"
|
||||
lib_utils::print_warning "${global_container}: testing connection (bootstrapping ~${_sleep})"
|
||||
sleep "$_sleep" # Give time to bootstrap
|
||||
# TODO: run timer to verify response (and fail if N times if no response)
|
||||
docker exec -it "$global_container" \
|
||||
/bin/bash -i -c "
|
||||
proxychains curl -s https://check.torproject.org 2>/dev/null \
|
||||
| grep -B3 'Your IP address appears to be' \
|
||||
| sed -e 's/^ //g' -e '\$ s/[^\\.0-9]//g' -e '/^\$/d' -e '2,3d'" || lib_utils::die_fatal
|
||||
}
|
||||
|
||||
function tor::stop()
|
||||
{
|
||||
if ! docker container inspect -f '{{.State.Running}}' "$tor_container" &>/dev/null; then
|
||||
lib_utils::print_error "${tor_container}: container not running"
|
||||
return 1
|
||||
fi
|
||||
lib_utils::print_warning "${tor_container}: stopping container"
|
||||
docker container stop "$tor_container" &>/dev/null \
|
||||
&& lib_utils::print_info "${tor_container}: container stopped"
|
||||
}
|
||||
|
||||
function tor::restart()
|
||||
{
|
||||
tor::stop
|
||||
tor::start
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
local -r _usage="
|
||||
\e[32mDescription:\e[0m
|
||||
|
||||
Connect docker-finance container's \`fetch\` to The Onion Router.
|
||||
|
||||
\e[32mUsage:\e[0m
|
||||
|
||||
\e[37;2m# Client (host) command\e[0m
|
||||
$ dfi $instance plugins repo${global_arg_delim_1}$(basename $0) <{start|up}|restart|{stop|down}>
|
||||
|
||||
\e[37;2m# Container command (see \`fetch\` help for usage)\e[0m
|
||||
$ dfi <profile${global_arg_delim_1}subprofile> fetch help
|
||||
"
|
||||
|
||||
case "$1" in
|
||||
start | up)
|
||||
tor::start
|
||||
;;
|
||||
stop | down)
|
||||
tor::stop
|
||||
;;
|
||||
restart)
|
||||
tor::restart
|
||||
;;
|
||||
*)
|
||||
lib_utils::die_usage "$_usage"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
# vim: sw=2 sts=2 si ai et
|
||||
@@ -124,6 +124,9 @@ function main()
|
||||
\e[37;2m# Print current version of 'docker-finance' and client/container ('finance') dependencies\e[0m
|
||||
$ dfi archlinux${global_arg_delim_1}${USER}:default version type${global_arg_delim_2}all
|
||||
|
||||
\e[37;2m# Print Tor plugin's usage help\e[0m
|
||||
$ dfi archlinux${global_arg_delim_1}${USER}:default plugins repo${global_arg_delim_1}tor.bash help
|
||||
|
||||
\e[37;2m#\e[0m
|
||||
\e[37;2m# Dev-tools platform\e[0m
|
||||
\e[37;2m#\e[0m
|
||||
|
||||
@@ -79,6 +79,10 @@ function lib_fetch::__parse_args()
|
||||
|
||||
(block)chain${global_arg_delim_2}<blockchain[${global_arg_delim_3}blockchain${global_arg_delim_1}subaccount]>
|
||||
|
||||
Tor (proxy):
|
||||
|
||||
tor${global_arg_delim_2}<{on|true}|{off|false}> (default 'off')
|
||||
|
||||
\e[32mExamples:\e[0m
|
||||
|
||||
\e[37;2m#\e[0m
|
||||
@@ -136,6 +140,14 @@ function lib_fetch::__parse_args()
|
||||
|
||||
\e[37;2m# Fetch specific blockchain/subaccount/address for metamask\e[0m
|
||||
$ $global_usage account${global_arg_delim_2}metamask chain${global_arg_delim_2}ethereum/phone:wallet-1/0x236ba53B56FEE4901cdac3170D17f827DF43E969
|
||||
|
||||
\e[37;2m# Fetch given blochchain-based subaccounts for current year, over the Tor network\e[0m
|
||||
$ $global_usage account${global_arg_delim_2}metamask${global_arg_delim_3}ledger blockchain${global_arg_delim_2}ethereum${global_arg_delim_3}polygon${global_arg_delim_3}tezos${global_arg_delim_3}algorand tor${global_arg_delim_2}on
|
||||
|
||||
\e[32mNotes:\e[0m
|
||||
|
||||
- For all commands, you can proxy your fetch through Tor with the \`tor${global_arg_delim_2}on\` option
|
||||
* IMPORTANT: client-side \`tor\` plugin must be started *prior* to fetch
|
||||
"
|
||||
|
||||
#
|
||||
@@ -151,6 +163,7 @@ function lib_fetch::__parse_args()
|
||||
&& [[ ! "$_arg" =~ ^account[s]?${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^(^block)?chain[s]?${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^year[s]?${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^tor${global_arg_delim_2} ]] \
|
||||
&& lib_utils::die_usage "$_usage"
|
||||
done
|
||||
|
||||
@@ -193,6 +206,11 @@ function lib_fetch::__parse_args()
|
||||
local _arg_year="${_arg:${_len}}"
|
||||
[ -z "$_arg_year" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^tor$ ]]; then
|
||||
local _arg_tor="${_arg:${_len}}"
|
||||
[ -z "$_arg_tor" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
done
|
||||
|
||||
#
|
||||
@@ -247,6 +265,14 @@ function lib_fetch::__parse_args()
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arg: tor
|
||||
if [ ! -z "$_arg_tor" ]; then
|
||||
# Need a valid arg
|
||||
if [[ -z "$_arg_all" && -z "$_arg_price" && -z "$_arg_account" ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Test argument values, set globals
|
||||
#
|
||||
@@ -318,6 +344,12 @@ function lib_fetch::__parse_args()
|
||||
global_arg_year="$(date +%Y)" # Set default current
|
||||
declare -gr global_arg_year
|
||||
fi
|
||||
|
||||
# Arg: tor
|
||||
if [ ! -z "$_arg_tor" ]; then
|
||||
[[ ! "$_arg_tor" =~ ^on$|^true$|^off$|^false$ ]] && lib_utils::die_usage "$_usage"
|
||||
declare -gr global_arg_tor="$_arg_tor"
|
||||
fi
|
||||
}
|
||||
|
||||
function lib_fetch::__fetch()
|
||||
@@ -752,15 +784,30 @@ function lib_fetch::__fetch_exec()
|
||||
[ -z "$_subtype" ] && lib_utils::die_fatal
|
||||
|
||||
local _dir="${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/fetch"
|
||||
|
||||
local _ifs="$IFS"
|
||||
IFS=' '
|
||||
|
||||
# TODO: remove no-limit after internal fetching writes per-paginated instead of per-fetch
|
||||
local _php=("/usr/bin/php" "-d" "memory_limit=\"-1\"" "-d" "include_path=\"/usr/local/lib:${_dir}\"")
|
||||
lib_utils::print_debug "${_php[@]}"
|
||||
#
|
||||
# Setup fetch
|
||||
#
|
||||
|
||||
"${_php[@]}" "${_dir}/fetch.php" "$_type" "$_subtype"
|
||||
local _exec=()
|
||||
[[ "$global_arg_tor" =~ ^on$|^true$ ]] && _exec+=("proxychains") # Wrap with proxychains
|
||||
|
||||
# Test for Tor plugin
|
||||
if ! "${_exec[@]}" curl -s "https://check.torproject.org" &>/dev/null; then
|
||||
lib_utils::die_fatal "Tor plugin not started (or needs restart)"
|
||||
fi
|
||||
|
||||
# TODO: remove no-limit after internal fetching writes per-paginated instead of per-fetch
|
||||
_exec+=("/usr/bin/php" "-d" "memory_limit=\"-1\"" "-d" "include_path=\"/usr/local/lib:${_dir}\"")
|
||||
lib_utils::print_debug "${_exec[@]}"
|
||||
|
||||
#
|
||||
# Execute fetch
|
||||
#
|
||||
|
||||
"${_exec[@]}" "${_dir}/fetch.php" "$_type" "$_subtype"
|
||||
IFS="$_ifs"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user