From 5e5ca1904b65161d9e6f5b7d3fee713d1a59a788 Mon Sep 17 00:00:00 2001 From: zjx20 Date: Tue, 30 Aug 2022 13:01:51 +0800 Subject: [PATCH] Fix dsocks support --- socksproxyenv.sample | 23 ++++++++++------ supports/dsocks | 65 ++++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/socksproxyenv.sample b/socksproxyenv.sample index a9d2844..1a59e33 100644 --- a/socksproxyenv.sample +++ b/socksproxyenv.sample @@ -45,15 +45,17 @@ LOAD_SUPPORT mvn # For example, to export FTP_PROXY: # EXPORT_ENV FTP_PROXY "http://${SOCKS_CLI_HTTP_PROXY}" -EXPORT_ENV FOO "this is an example of EXPORT_ENV and should be removed!" +# EXPORT_ENV FOO "this is an example of EXPORT_ENV!" # However, not all program has built-in proxy support. To settle these # situations, dsocks (https://github.com/zjx20/dsocks) has been integrated # into socks-cli. # -# *PLEASE NOTICE* that dsocks doesn't work well with system binaries on -# macOS 10.11+ because of the SIP feature (a.k.a. System Integrity Protection). +# *PLEASE NOTICE* that dsocks doesn't work for system binaries (e.g. /bin/*, +# /usr/bin/*) on macOS 10.11+ because of the SIP (System Integrity Protection). +# But it should still work with commands installed by package management tools +# such as HomeBrew. # Uncomment the line "LOAD_SUPPORT dsocks" to enable the dsocks support. # "git" and "gcc" will be needed to bootstrap dsocks. @@ -61,13 +63,16 @@ EXPORT_ENV FOO "this is an example of EXPORT_ENV and should be removed!" # LOAD_SUPPORT dsocks # And then use the SOCKSIFY DSL to define which command to be socksified. -# For example: +# +# Uncomment any SOCKSIFY line to give a try: +# # # socksify the curl command # SOCKSIFY curl -# # socksify the python command and use "/usr/bin/env python" to run python -# SOCKSIFY python /usr/bin/env python # -# After socksifying the "python" command, for example, you can run the -# following code snippet to verify it: +# # specifying "/usr/bin/env python" as the entrypoint of the socksified cmd. +# SOCKSIFY python3 /usr/bin/env python3 +# +# Assume that you had socksified the "python3" command, you can check your +# external ip by running: # -# python -c "import urllib2;print(urllib2.urlopen('http://fb.com/').read())" +# python3 -c "import urllib.request as r;print(r.urlopen('https://ipinfo.io/').read().decode('utf-8'))" diff --git a/supports/dsocks b/supports/dsocks index 1004775..a0bb1d0 100644 --- a/supports/dsocks +++ b/supports/dsocks @@ -1,6 +1,25 @@ #!/bin/bash # The shebang is just a hint for editors. +function _socks_cli_clean_dsocks_tmp() { + local tmp_path="${SOCKS_CLI_DIR}/tmp/" + # First pass: remove command shadows if the shell has been dead. + find "${tmp_path}" -name "_shell_pid" -print0 | + while IFS= read -r -d '' file; do + pid="$(tr -d '\n\r' < "${file}")" + if [ "${pid}" = "$$" ]; then + # Ignore the current shell + continue + fi + if ! pgrep -F "${file}" > /dev/null; then + find "$(dirname "${file}")" -type f -delete + fi + done + + # Second pass: remove empty directories recursively. + find "${tmp_path}" -empty -type d -delete +} + function socks_cli_activate_dsocks() { _socks_cli_dsocks_lib="${SOCKS_CLI_DIR}/dsocks/libdsocks.so" "${SOCKS_CLI_DIR}/sh/bootstrap-dsocks.sh" @@ -10,6 +29,8 @@ function socks_cli_activate_dsocks() { return 1 fi + _socks_cli_clean_dsocks_tmp + # Create a dedicated temporary folder for each shell process. # Since the maximum pid number in unix-like OS is typically # not greater than 999999, we can distribute the temporary @@ -21,7 +42,9 @@ function socks_cli_activate_dsocks() { local name=$((shell_pid%100)) local tmp_path="${SOCKS_CLI_DIR}/tmp/${level_one}/${level_two}/${name}" mkdir -p "${tmp_path}" - [ -n "${tmp_path}" ] && rm -f "${tmp_path}/*" + # Remove existing command shadows + [ -n "${tmp_path}" ] && find "${tmp_path}/" -type f -delete + echo "${shell_pid}" > "${tmp_path}/_shell_pid" local preappend="${tmp_path}" if [ -n "${PATH}" ]; then @@ -40,18 +63,6 @@ function socks_cli_deactivate_dsocks() { unset _socks_cli_socksify } -function _sed_escape() { - echo "$1" | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g' -} -export -f _sed_escape > /dev/null - -function socks_cli_replace() { - local search=$(_sed_escape "$2") - local replace=$(_sed_escape "$3") - echo "$1" | sed "s/${search}/${replace}/g" -} -export -f socks_cli_replace > /dev/null - function SOCKSIFY() { if [ "${_socks_cli_socksify}" != "1" ]; then return 1 @@ -63,12 +74,24 @@ function SOCKSIFY() { local hook_command="$1" local start_command="${@:2}" - local cmd_path="${_socks_cli_socksify_tmp_path}/${hook_command}" - cat <<-EOF > "${cmd_path}" -#!/bin/bash -# maintain the PATH env to avoid endless loop -export PATH="\$(socks_cli_replace "\$PATH" "${_socks_cli_socksify_path_preappend}" "")" -"${SOCKS_CLI_DIR}/dsocks/socksify" ${start_command} "\$@" -EOF - chmod +x "${cmd_path}" + if [ -z "$start_command" ]; then + start_command="${hook_command}" + fi + local cmd_shadow="${_socks_cli_socksify_tmp_path}/${hook_command}" + cat <<-EOF > "${cmd_shadow}" + #!/bin/bash + function _sed_escape() { + echo "\$1" | sed -e 's/\\\\/\\\\\\\\/g; s/\\//\\\\\\//g; s/&/\\\\\\&/g' + } + function socks_cli_replace() { + local search=\$(_sed_escape "\$2") + local replace=\$(_sed_escape "\$3") + echo "\$1" | sed "s/\${search}/\${replace}/g" + } + # remove the current folder from the PATH, + # to avoid recursively invoking this script. + export PATH="\$(socks_cli_replace "\$PATH" "${_socks_cli_socksify_path_preappend}" "")" + "${SOCKS_CLI_DIR}/dsocks/socksify" ${start_command} "\$@" + EOF + chmod +x "${cmd_shadow}" }