Skip to content

Instantly share code, notes, and snippets.

@zhiguangwang
Created August 4, 2019 07:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhiguangwang/fa41d0225cc71a6a0ae494eb0ea8e68b to your computer and use it in GitHub Desktop.
Save zhiguangwang/fa41d0225cc71a6a0ae494eb0ea8e68b to your computer and use it in GitHub Desktop.
Configure the Docker daemon to use ss-local as HTTP/HTTPS proxy.
#!/bin/bash
set -e
function print_usage {
echo
echo "Usage: docker-sslocal.sh [OPTIONS]"
echo
echo "This script is to configure the Docker daemon to use ss-local as HTTP/HTTPS proxy."
echo
echo "Note: You must run this script as root."
echo
echo "Options:"
echo
echo -e " --server-host\t\t(Required) IP or hostname of the Shadowsocks server"
echo -e " --server-port\t\t(Required) Port number of the Shadowsocks server"
echo -e " --server-password\t(Required) Password of the Shadowsocks server"
echo
echo -e " --server-name\t\t(Optional) The custom name for the Shadowsocks server. Default value: local"
echo -e " --server-cipher\t(Optional) The cipher method used by the Shadowsocks server. Default value: xchacha20-ietf-poly1305"
echo -e " --local-port\t\t(Optional) The local port number used by ss-local. Default value: 1080"
echo
echo
echo "Example:"
echo
echo " docker-sslocal.sh --server-name tokyo --server-host 1.1.1.1 --server-port 8443 --server-password foobar"
echo
}
function log {
local readonly level="$1"
local readonly message="$2"
local readonly timestamp=$(date +"%Y-%m-%d %H:%M:%S")
>&2 echo -e "${timestamp} [${level}] ${message}"
}
function log_info {
local readonly message="$1"
log "INFO" "$message"
}
function log_error {
local readonly message="$1"
log "ERROR" "$message"
}
function assert_running_as_root {
if [[ "$EUID" -ne 0 ]]; then
log_error "Please run as root."
exit 1
fi
}
function assert_not_empty {
local readonly arg_name="$1"
local readonly arg_value="$2"
if [[ -z "$arg_value" ]]; then
log_error "The value for '$arg_name' cannot be empty"
exit 1
fi
}
function assert_is_installed {
local readonly name="$1"
if [[ ! $(command -v ${name}) ]]; then
log_error "The binary '$name' is required by this script but is not installed or in the system's PATH."
exit 1
fi
}
function install_shadowsocks_libev {
apt-get install -y shadowsocks-libev
systemctl stop shadowsocks-libev.service
systemctl disable shadowsocks-libev.service
}
function generate_sslocal_systemd_dropin {
local readonly systemd_dropin_dir='/etc/systemd/system/shadowsocks-libev-local@.service.d'
mkdir -p "$systemd_dropin_dir"
cat > "$systemd_dropin_dir/override.conf" <<EOF
[Service]
User=nobody
Group=nogroup
LimitNOFILE=32768
EOF
}
function generate_sslocal_config {
local readonly server_name="$1"
local readonly server_host="$2"
local readonly server_port="$3"
local readonly server_password="$4"
local readonly server_cipher="$5"
local readonly local_port="$6"
local readonly sslocal_config_path="/etc/shadowsocks-libev/$server_name.json"
cat > "$sslocal_config_path" <<EOF
{
"server": "$server_host",
"server_port": $server_port,
"local_port": $local_port,
"password": "$server_password",
"timeout": 60,
"method": "$server_cipher",
"mode": "tcp_only",
"fast_open": true
}
EOF
}
function start_sslocal {
local readonly server_name="$1"
systemctl daemon-reload
systemctl enable "shadowsocks-libev-local@$server_name.service"
systemctl start shadowsocks-libev-local@$server_name.service
}
# https://docs.docker.com/config/daemon/systemd/#httphttps-proxy
function configure_docker_daemon {
local readonly local_port="$1"
local readonly systemd_dropin_dir='/etc/systemd/system/docker.service.d'
mkdir -p "$systemd_dropin_dir"
cat > "$systemd_dropin_dir/override.conf" <<EOF
[Service]
Environment="ALL_PROXY=socks5h://127.0.0.1:$local_port"
EOF
systemctl daemon-reload
systemctl restart docker
}
function run {
local server_name="local"
local server_host=""
local server_port=""
local server_password=""
local server_cipher="xchacha20-ietf-poly1305"
local local_port="1080"
while [[ $# > 0 ]]; do
local key="$1"
case "$key" in
--server-name)
assert_not_empty "$key" "$2"
server_name="$2"
shift
;;
--server-host)
assert_not_empty "$key" "$2"
server_host="$2"
shift
;;
--server-port)
assert_not_empty "$key" "$2"
server_port="$2"
shift
;;
--server-password)
assert_not_empty "$key" "$2"
server_password="$2"
shift
;;
--server-cipher)
assert_not_empty "$key" "$2"
server_cipher="$2"
shift
;;
--local-port)
assert_not_empty "$key" "$2"
local_port="$2"
shift
;;
--help)
print_usage
exit
;;
*)
log_error "Unrecognized argument: $key"
print_usage
exit 1
;;
esac
shift
done
assert_running_as_root
assert_is_installed "docker"
assert_not_empty "--server-host" "$server_host"
assert_not_empty "--server-port" "$server_port"
assert_not_empty "--server-password" "$server_password"
install_shadowsocks_libev
generate_sslocal_systemd_dropin
generate_sslocal_config \
"$server_name" \
"$server_host" \
"$server_port" \
"$server_password" \
"$server_cipher" \
"$local_port"
start_sslocal "$server_name"
configure_docker_daemon "$local_port"
}
run "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment