Skip to content

Instantly share code, notes, and snippets.

@bibendi
Last active October 12, 2025 18:13
Show Gist options
  • Select an option

  • Save bibendi/8ed34b528313ac9dfa1bcba82e65f44a to your computer and use it in GitHub Desktop.

Select an option

Save bibendi/8ed34b528313ac9dfa1bcba82e65f44a to your computer and use it in GitHub Desktop.
Linux Shadowsocks Client Proxy
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# 1) Установить privoxy (если ещё не установлен)
sudo apt update
sudo apt install -y privoxy
# 2) Бэкап текущего конфига
sudo cp /etc/privoxy/config /etc/privoxy/config.bak
# 3) Прописать listen-address 0.0.0.0:8118 (заменит существующую строку или добавит)
sudo sed -i '/^listen-address/ d' /etc/privoxy/config
echo "listen-address 0.0.0.0:8118" | sudo tee -a /etc/privoxy/config >/dev/null
# 4) Добавить forward-socks5t правило (перенаправлять через локальный SOCKS5 127.0.0.1:1080)
# Если строка уже есть — команда добавит ещё одну (это безопасно), можно удалить дубликаты вручную при необходимости.
grep -q "^forward-socks5t / 127.0.0.1:1080 \\." /etc/privoxy/config || \
echo "forward-socks5t / 127.0.0.1:1080 ." | sudo tee -a /etc/privoxy/config >/dev/null
# 5) Перезапустить privoxy
sudo systemctl restart privoxy
sudo systemctl enable privoxy
# --- тест подключения ---
echo
echo "→ Тестируем внешний IP через SOCKS5 127.0.0.1:1080"
IP_BEFORE=$(curl -s https://api.ipify.org || echo "нет сети")
IP_AFTER=$(curl -s -x 127.0.0.1:8118 https://api.ipify.org || echo "нет прокси")
echo " IP без прокси : $IP_BEFORE"
echo " IP через SOCKS: $IP_AFTER"
if [[ "$IP_AFTER" != "$IP_BEFORE" && -n "$IP_AFTER" ]]; then
echo
echo "✅ Готово — трафик идёт через $SERVER (виден внешний IP прокси)."
else
echo
echo "⚠️ Внимание: IP не изменился. Проверь пароль/порт/доступность сервера."
fi
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
CONFIG_DIR="/etc/shadowsocks-libev"
CONFIG_FILE="$CONFIG_DIR/config.json"
SERVICE_CLIENT="shadowsocks-local.service"
SERVICE_SERVER="shadowsocks-libev.service"
banner(){ echo -e "\n=== $1 ==="; }
banner "Установка Shadowsocks-libev (клиент) — простая версия (без obfs)"
read -rp "Вставь ss:// ссылку (из Outline Manager или аналог): " SSURL
if [[ ! "$SSURL" =~ ^ss:// ]]; then
echo "Ошибка: строка должна начинаться с ss://"
exit 1
fi
banner "Установка пакетов..."
apt update -y
apt install -y shadowsocks-libev curl || { echo "Ошибка установки пакетов"; exit 1; }
# --- парсим ss:// ---
# убираем префикс и возможный ?outline=1
TMP=$(echo "$SSURL" | sed -E 's#^ss://##; s#/?outline=1##; s#/$##')
USERINFO=${TMP%@*}
HOSTPART=${TMP#*@}
# Попытка декодировать userinfo как base64(method:password)
DECODED=$(echo "$USERINFO" | sed 's/-/+/g; s/_/\//g' | base64 -d 2>/dev/null || true)
if [[ "$DECODED" == *:* ]]; then
METHOD=${DECODED%%:*}
PASSWORD=${DECODED#*:}
else
# формат method:password@host:port (не base64)
METHOD=${USERINFO%%:*}
PASSWORD=${USERINFO#*:}
fi
# Сервер и порт (порт может содержать /..., отрезаем)
SERVER=$(echo "$HOSTPART" | cut -d: -f1)
PORT=$(echo "$HOSTPART" | cut -d: -f2 | cut -d'/' -f1)
# валидация
if [[ -z "$SERVER" || -z "$PORT" || -z "$PASSWORD" || -z "$METHOD" ]]; then
echo "Ошибка парсинга ss:// строки. Проверь формат."
exit 1
fi
echo
echo "→ Параметры:"
echo " server = $SERVER"
echo " port = $PORT"
echo " method = $METHOD"
# --- создаём конфиг (plain, без obfs) ---
echo
echo "→ Пишем конфиг в $CONFIG_FILE"
mkdir -p "$CONFIG_DIR"
cat > /tmp/ss-config.json <<EOF
{
"server": "$SERVER",
"server_port": $PORT,
"local_address": "0.0.0.0",
"local_port": 1080,
"password": "$PASSWORD",
"method": "$METHOD",
"mode": "tcp_and_udp"
}
EOF
# перемещаем в /etc с правами
mv /tmp/ss-config.json "$CONFIG_FILE"
chmod 644 "$CONFIG_FILE"
chown root:root "$CONFIG_FILE"
chmod 755 "$CONFIG_DIR"
# --- отключаем серверный юнит, если он активен (чтобы не конфликтовал) ---
if systemctl list-unit-files | grep -q "^${SERVICE_SERVER}"; then
if systemctl is-active --quiet "${SERVICE_SERVER}"; then
echo "→ Отключаем и останавливаем серверный юнит ${SERVICE_SERVER} (чтобы не мешал клиенту)"
systemctl disable --now "${SERVICE_SERVER}" || true
fi
fi
# --- создаём unit для клиента ---
echo
echo "→ Создаём systemd‑юнит $SERVICE_CLIENT"
cat > /etc/systemd/system/${SERVICE_CLIENT} <<'UNIT'
[Unit]
Description=Shadowsocks-libev local (client)
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/bin/ss-local -c /etc/shadowsocks-libev/config.json
Restart=always
User=root
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
UNIT
# Перезагрузка systemd и запуск
systemctl daemon-reload
systemctl enable --now "${SERVICE_CLIENT}"
sleep 2
if systemctl is-active --quiet "${SERVICE_CLIENT}"; then
echo "✅ Служба ${SERVICE_CLIENT} запущена"
else
echo "❌ Не удалось запустить ${SERVICE_CLIENT}. Смотри лог:"
journalctl -u "${SERVICE_CLIENT}" -n 50 --no-pager
exit 1
fi
# --- тест подключения ---
echo
echo "→ Тестируем внешний IP через SOCKS5 127.0.0.1:1080"
IP_BEFORE=$(curl -s https://api.ipify.org || echo "нет сети")
IP_AFTER=$(curl -s --socks5 127.0.0.1:1080 https://api.ipify.org || echo "нет прокси")
echo " IP без прокси : $IP_BEFORE"
echo " IP через SOCKS: $IP_AFTER"
if [[ "$IP_AFTER" != "$IP_BEFORE" && -n "$IP_AFTER" ]]; then
echo
echo "✅ Готово — трафик идёт через $SERVER (виден внешний IP прокси)."
else
echo
echo "⚠️ Внимание: IP не изменился. Проверь пароль/порт/доступность сервера."
echo "Просмотр последних логов службы:"
journalctl -u "${SERVICE_CLIENT}" -n 50 --no-pager
fi
echo
echo "Файл конфига: $CONFIG_FILE"
echo "Юнит службы : /etc/systemd/system/${SERVICE_CLIENT}"
echo "Локальный SOCKS5: 127.0.0.1:1080"
echo
SERVICE = shadowsocks-local
CONFIG = /etc/shadowsocks-libev/config.json
GREEN = \033[0;32m
RED = \033[0;31m
RESET = \033[0m
.PHONY: help install start stop status enable disable test logs
help:
@echo "Доступные цели:"
@echo " make install – установить и настроить клиент"
@echo " make start – запустить службу"
@echo " make stop – остановить службу"
@echo " make status – показать состояние"
@echo " make enable – включить автозапуск"
@echo " make disable – выключить автозапуск"
@echo " make test – проверить IP‑адрес через SOCKS"
@echo " make logs – последние строки лога"
install:
@bash ./install-ss-client.sh
@bash ./install-privoxy.sh
start:
sudo systemctl start $(SERVICE)
stop:
sudo systemctl stop $(SERVICE)
status:
sudo systemctl status $(SERVICE) --no-pager
enable:
sudo systemctl enable $(SERVICE)
disable:
sudo systemctl disable $(SERVICE)
test:
@echo "Проверяем IP..."
@IP_NORMAL=$$(curl -s https://api.ipify.org); \
IP_PROXY=$$(curl -s -x 127.0.0.1:8118 https://api.ipify.org); \
echo "IP без прокси : $$IP_NORMAL"; \
echo "IP через прокси: $$IP_PROXY"; \
if [ "$$IP_NORMAL" != "$$IP_PROXY" ] && [ -n "$$IP_PROXY" ]; then \
echo -e "$(GREEN)✅ ОК — соединение через Outline$(RESET)"; \
else \
echo -e "$(RED)❌ FAIL — IP не изменился$(RESET)"; \
fi
logs:
sudo journalctl -u $(SERVICE) -n 50 --no-pager
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment