Fix: 3X-UI status shows SOCKS5+JSON; rewrite AmneziaWG backend per bandju reference

Made-with: Cursor
This commit is contained in:
anten-ka
2026-03-20 16:01:12 +03:00
parent 0a4b0c4620
commit 9c41c93507

240
warp.sh
View File

@@ -44,6 +44,8 @@ MODE=""
CONTAINER="" CONTAINER=""
AWG_VPN_CONF="" AWG_VPN_CONF=""
AWG_VPN_IF=""
AWG_VPN_QUICK_CMD=""
AWG_CLIENTS_TABLE="" AWG_CLIENTS_TABLE=""
AWG_START_SH="" AWG_START_SH=""
AWG_SUBNET="" AWG_SUBNET=""
@@ -96,7 +98,8 @@ detect_mode() {
command -v docker &>/dev/null && has_docker=1 command -v docker &>/dev/null && has_docker=1
if [ "$has_docker" -eq 1 ]; then if [ "$has_docker" -eq 1 ]; then
local awg_ct local awg_ct
awg_ct=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia" | head -1) awg_ct=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -E '^amnezia-awg2$|^amnezia-awg$' | head -1)
[ -z "$awg_ct" ] && awg_ct=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia" | head -1)
[ -n "$awg_ct" ] && has_amnezia=1 [ -n "$awg_ct" ] && has_amnezia=1
fi fi
systemctl is-active x-ui &>/dev/null 2>&1 && has_3xui=1 systemctl is-active x-ui &>/dev/null 2>&1 && has_3xui=1
@@ -367,10 +370,33 @@ show_status_3xui() {
local st; st=$(get_warp_status_3xui) local st; st=$(get_warp_status_3xui)
local sc="$RED"; [[ "$st" == "Подключён" ]] && sc="$GREEN"; [[ "$st" == "Отключён" ]] && sc="$YELLOW" local sc="$RED"; [[ "$st" == "Подключён" ]] && sc="$GREEN"; [[ "$st" == "Отключён" ]] && sc="$YELLOW"
echo -e " ${WHITE}Статус: ${sc}${st}${NC}" echo -e " ${WHITE}Статус: ${sc}${st}${NC}"
echo -e " ${WHITE}Порт SOCKS5: ${CYAN}127.0.0.1:${SOCKS_PORT}${NC}"
echo -e " ${WHITE}Реальный IP: ${GREEN}${MY_IP}${NC}" echo -e " ${WHITE}Реальный IP: ${GREEN}${MY_IP}${NC}"
is_warp_running_3xui && echo -e " ${WHITE}WARP IP: ${GREEN}$(get_warp_ip_3xui)${NC}" is_warp_running_3xui && echo -e " ${WHITE}WARP IP: ${GREEN}$(get_warp_ip_3xui)${NC}"
echo -e "\n ${CYAN}── warp-cli status ──${NC}"
echo -e "\n${CYAN}── Настройки SOCKS5-прокси ──${NC}\n"
echo -e " ${WHITE}Адрес:${NC} ${GREEN}127.0.0.1${NC}"
echo -e " ${WHITE}Порт:${NC} ${GREEN}${SOCKS_PORT}${NC}"
echo -e " ${WHITE}Прокси:${NC} ${CYAN}socks5h://127.0.0.1:${SOCKS_PORT}${NC}"
echo -e "\n${CYAN}── JSON Outbound для 3X-UI (скопируйте в панель) ──${NC}\n"
echo -e "${GREEN}"
cat <<EOF
{
"tag": "warp",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": ${SOCKS_PORT}
}
]
}
}
EOF
echo -e "${NC}"
echo -e "${CYAN}── warp-cli status ──${NC}"
warp-cli --accept-tos status 2>/dev/null | while IFS= read -r l; do echo -e " ${WHITE}$l${NC}"; done warp-cli --accept-tos status 2>/dev/null | while IFS= read -r l; do echo -e " ${WHITE}$l${NC}"; done
echo ""; read -p "Enter..." echo ""; read -p "Enter..."
} }
@@ -394,23 +420,31 @@ uninstall_3xui() {
awg_pick_container() { awg_pick_container() {
if [ -n "${CONTAINER:-}" ]; then if [ -n "${CONTAINER:-}" ]; then
docker inspect "$CONTAINER" &>/dev/null && return 0 docker exec "$CONTAINER" sh -c "true" 2>/dev/null && return 0
CONTAINER=""
fi fi
local -a containers=() local -a containers=()
while IFS= read -r name; do mapfile -t containers < <(docker ps --format '{{.Names}}' | grep -E '^amnezia-awg2$|^amnezia-awg$' 2>/dev/null || true)
[ -n "$name" ] && containers+=("$name")
done < <(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia")
if [ ${#containers[@]} -eq 0 ]; then if [ ${#containers[@]} -eq 0 ]; then
echo -e "${RED}Не найден Docker-контейнер AmneziaWG.${NC}" mapfile -t containers < <(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia" || true)
fi
if [ ${#containers[@]} -eq 0 ]; then
echo -e "${RED}Контейнеры amnezia-awg / amnezia-awg2 не найдены.${NC}"
echo -e "${WHITE}Убедитесь, что AmneziaWG запущен через Docker.${NC}" echo -e "${WHITE}Убедитесь, что AmneziaWG запущен через Docker.${NC}"
return 1 return 1
elif [ ${#containers[@]} -eq 1 ]; then elif [ ${#containers[@]} -eq 1 ]; then
CONTAINER="${containers[0]}" CONTAINER="${containers[0]}"
else else
echo -e "\n${CYAN}Найдено несколько контейнеров:${NC}" echo -e "\n${CYAN}Доступные контейнеры:${NC}"
for i in "${!containers[@]}"; do echo -e " ${GREEN}$((i+1)))${NC} ${containers[$i]}"; done local i=1
for c in "${containers[@]}"; do echo -e " ${GREEN}$i)${NC} $c"; ((i++)); done
echo -e " ${DIM}0) Отмена${NC}"
while true; do while true; do
read -p "Выберите (1-${#containers[@]}): " ch read -p "Выберите контейнер: " ch
[ "$ch" = "0" ] && return 1
[[ "$ch" =~ ^[0-9]+$ ]] && (( ch >= 1 && ch <= ${#containers[@]} )) && { CONTAINER="${containers[$((ch-1))]}"; break; } [[ "$ch" =~ ^[0-9]+$ ]] && (( ch >= 1 && ch <= ${#containers[@]} )) && { CONTAINER="${containers[$((ch-1))]}"; break; }
done done
fi fi
@@ -419,28 +453,34 @@ awg_pick_container() {
} }
awg_load_container_data() { awg_load_container_data() {
local vpn_conf="" if [ "$CONTAINER" = "amnezia-awg2" ]; then
for f in /opt/amnezia/awg/wg0.conf /etc/wireguard/wg0.conf /opt/amnezia/wg/wg0.conf; do AWG_VPN_CONF="/opt/amnezia/awg/awg0.conf"
if docker exec "$CONTAINER" sh -c "[ -f '$f' ]" 2>/dev/null; then AWG_VPN_IF="awg0"
vpn_conf="$f"; break AWG_VPN_QUICK_CMD="awg-quick"
fi else
done AWG_VPN_CONF="/opt/amnezia/awg/wg0.conf"
[ -z "$vpn_conf" ] && { echo -e "${RED}Не найден VPN-конфиг в контейнере.${NC}"; return 1; } AWG_VPN_IF="wg0"
AWG_VPN_CONF="$vpn_conf" AWG_VPN_QUICK_CMD="wg-quick"
fi
for f in /opt/amnezia/awg/clientsTable /opt/amnezia/clientsTable /etc/wireguard/clientsTable; do AWG_CLIENTS_TABLE="/opt/amnezia/awg/clientsTable"
if docker exec "$CONTAINER" sh -c "[ -f '$f' ]" 2>/dev/null; then AWG_START_SH="/opt/amnezia/start.sh"
AWG_CLIENTS_TABLE="$f"; break
fi
done
for f in /opt/amnezia/start.sh /opt/amnezia/awg/start.sh; do docker exec "$CONTAINER" sh -c "[ -f '$AWG_VPN_CONF' ]" 2>/dev/null || {
if docker exec "$CONTAINER" sh -c "[ -f '$f' ]" 2>/dev/null; then for f in /opt/amnezia/awg/wg0.conf /opt/amnezia/awg/awg0.conf /etc/wireguard/wg0.conf; do
AWG_START_SH="$f"; break if docker exec "$CONTAINER" sh -c "[ -f '$f' ]" 2>/dev/null; then
fi AWG_VPN_CONF="$f"
done break
fi
done
}
AWG_SUBNET=$(docker exec "$CONTAINER" sh -c "sed -n 's/^Address = \(.*\)$/\1/p' '$AWG_VPN_CONF' | head -1 | cut -d',' -f1" 2>/dev/null | tr -d '\r') docker exec "$CONTAINER" sh -c "[ -f '$AWG_VPN_CONF' ]" 2>/dev/null || {
echo -e "${RED}Не найден конфиг VPN в контейнере: $AWG_VPN_CONF${NC}"
return 1
}
AWG_SUBNET=$(docker exec "$CONTAINER" sh -c "sed -n 's/^Address = \(.*\)$/\1/p' '$AWG_VPN_CONF' | head -n1 | cut -d',' -f1" 2>/dev/null | tr -d '\r')
return 0 return 0
} }
@@ -510,12 +550,14 @@ awg_resolve_endpoint() {
awg_build_warp_conf() { awg_build_warp_conf() {
local endpoint_ip="$1" local endpoint_ip="$1"
local pk; pk=$(awk -F' = ' '/^PrivateKey = /{print $2}' "$WGCF_PROFILE") local pk pub addr
local pub; pub=$(awk -F' = ' '/^PublicKey = /{print $2}' "$WGCF_PROFILE") pk=$(awk -F' = ' '/^PrivateKey = /{print $2}' "$WGCF_PROFILE")
local addr; addr=$(awk -F' = ' '/^Address = /{print $2}' "$WGCF_PROFILE" | cut -d',' -f1) pub=$(awk -F' = ' '/^PublicKey = /{print $2}' "$WGCF_PROFILE")
addr=$(awk -F' = ' '/^Address = /{print $2}' "$WGCF_PROFILE" | cut -d',' -f1)
docker exec "$CONTAINER" sh -c "mkdir -p '$AWG_WARP_DIR'" docker exec "$CONTAINER" sh -c "mkdir -p '$AWG_WARP_DIR'"
docker exec "$CONTAINER" sh -c "cat > '$AWG_WARP_CONF' <<'EOF' docker cp "$WGCF_PROFILE" "${CONTAINER}:${AWG_WARP_DIR}/wgcf-profile.conf" 2>/dev/null
docker exec "$CONTAINER" sh -c "cat > '$AWG_WARP_CONF' <<'WARPEOF'
[Interface] [Interface]
PrivateKey = ${pk} PrivateKey = ${pk}
Address = ${addr} Address = ${addr}
@@ -527,7 +569,7 @@ PublicKey = ${pub}
AllowedIPs = 0.0.0.0/0 AllowedIPs = 0.0.0.0/0
Endpoint = ${endpoint_ip}:2408 Endpoint = ${endpoint_ip}:2408
PersistentKeepalive = 25 PersistentKeepalive = 25
EOF WARPEOF
chmod 600 '$AWG_WARP_CONF'" chmod 600 '$AWG_WARP_CONF'"
} }
@@ -564,7 +606,6 @@ install_warp_awg() {
local ep; ep=$(awg_resolve_endpoint) || { read -p "Enter..."; return; }; echo -e "${GREEN}${ep}${NC}" local ep; ep=$(awg_resolve_endpoint) || { read -p "Enter..."; return; }; echo -e "${GREEN}${ep}${NC}"
echo -e "${YELLOW}[6/7]${NC} Сборка warp.conf в контейнере..." echo -e "${YELLOW}[6/7]${NC} Сборка warp.conf в контейнере..."
docker cp "$WGCF_PROFILE" "${CONTAINER}:${AWG_WARP_DIR}/wgcf-profile.conf" 2>/dev/null
awg_build_warp_conf "$ep"; echo -e "${GREEN}${NC}" awg_build_warp_conf "$ep"; echo -e "${GREEN}${NC}"
echo -e "${YELLOW}[7/7]${NC} Поднимаю warp-интерфейс..." echo -e "${YELLOW}[7/7]${NC} Поднимаю warp-интерфейс..."
@@ -572,7 +613,7 @@ install_warp_awg() {
awg_detect_warp_exit_ip awg_detect_warp_exit_ip
[ -n "$AWG_WARP_EXIT_IP" ] && echo -e "\n ${WHITE}WARP IP: ${GREEN}${AWG_WARP_EXIT_IP}${NC}" [ -n "$AWG_WARP_EXIT_IP" ] && echo -e "\n ${WHITE}WARP IP: ${GREEN}${AWG_WARP_EXIT_IP}${NC}"
echo -e "\n${GREEN}WARP установлен! Добавьте клиентов через п.5.${NC}" echo -e "\n${GREEN}WARP установлен! Добавьте клиентов через п.6.${NC}"
log_action "AWG INSTALL: endpoint=${ep}, warp_ip=${AWG_WARP_EXIT_IP}" log_action "AWG INSTALL: endpoint=${ep}, warp_ip=${AWG_WARP_EXIT_IP}"
read -p "Enter..." read -p "Enter..."
} }
@@ -603,7 +644,6 @@ rekey_warp_awg() {
echo -e "${YELLOW}[4/5]${NC} Генерация профиля..."; awg_generate_profile || { read -p "Enter..."; return; }; echo -e "${GREEN}${NC}" echo -e "${YELLOW}[4/5]${NC} Генерация профиля..."; awg_generate_profile || { read -p "Enter..."; return; }; echo -e "${GREEN}${NC}"
echo -e "${YELLOW}[5/5]${NC} Пересборка и запуск..." echo -e "${YELLOW}[5/5]${NC} Пересборка и запуск..."
local ep; ep=$(awg_resolve_endpoint) || { read -p "Enter..."; return; } local ep; ep=$(awg_resolve_endpoint) || { read -p "Enter..."; return; }
docker cp "$WGCF_PROFILE" "${CONTAINER}:${AWG_WARP_DIR}/wgcf-profile.conf" 2>/dev/null
awg_build_warp_conf "$ep" awg_build_warp_conf "$ep"
awg_warp_up || { read -p "Enter..."; return; } awg_warp_up || { read -p "Enter..."; return; }
awg_apply_rules awg_apply_rules
@@ -707,33 +747,65 @@ ${content}EOF
awg_parse_clients_table() { awg_parse_clients_table() {
AWG_CLIENT_NAMES=() AWG_CLIENT_NAMES=()
[ -z "${AWG_CLIENTS_TABLE:-}" ] && return 0
local raw; raw=$(docker exec "$CONTAINER" sh -c "cat '$AWG_CLIENTS_TABLE' 2>/dev/null || true" | tr -d '\r') local raw
raw=$(docker exec "$CONTAINER" sh -c "cat '$AWG_CLIENTS_TABLE' 2>/dev/null || true" | tr -d '\r')
[ -z "$raw" ] && return 0 [ -z "$raw" ] && return 0
declare -A key_to_name=() declare -A key_to_name=()
local pairs; pairs=$(echo "$raw" | awk ' local id_name_pairs
/"clientId"/ { s=$0; gsub(/.*"clientId"[[:space:]]*:[[:space:]]*"/,"",s); gsub(/".*/,"",s); cid=s } id_name_pairs=$(echo "$raw" | awk '
/"clientName"/ { s=$0; gsub(/.*"clientName"[[:space:]]*:[[:space:]]*"/,"",s); gsub(/".*/,"",s); name=s; /"clientId"/ {
if(cid!=""&&name!="") print cid"|"name }') s = $0
if [ -n "$pairs" ]; then gsub(/.*"clientId"[[:space:]]*:[[:space:]]*"/, "", s)
gsub(/".*/, "", s)
cid = s
}
/"clientName"/ {
s = $0
gsub(/.*"clientName"[[:space:]]*:[[:space:]]*"/, "", s)
gsub(/".*/, "", s)
name = s
if (cid != "" && name != "") {
print cid "|" name
}
}')
if [ -n "$id_name_pairs" ]; then
while IFS='|' read -r cid name; do while IFS='|' read -r cid name; do
[ -n "$cid" ] && [ -n "$name" ] && key_to_name["$cid"]="$name" [ -n "$cid" ] && [ -n "$name" ] && key_to_name["$cid"]="$name"
done <<< "$pairs" done <<< "$id_name_pairs"
fi fi
local peers; peers=$(docker exec "$CONTAINER" sh -c "cat '$AWG_VPN_CONF' 2>/dev/null || true" | tr -d '\r' | awk ' local conf_peers
/^\[Peer\]/ {pk="";ip=""} conf_peers=$(docker exec "$CONTAINER" sh -c "cat '$AWG_VPN_CONF' 2>/dev/null || true" | tr -d '\r' | awk '
/^PublicKey/ {s=$0; sub(/^[^=]*= */,"",s); pk=s} /^\[Peer\]/ { pubkey=""; ip="" }
/^AllowedIPs/ {s=$0; sub(/^[^=]*= */,"",s); ip=s; if(pk!=""&&ip!="") print pk"|"ip}') /^PublicKey/ {
if [ -n "$peers" ]; then s = $0
while IFS='|' read -r pk ip; do sub(/^[^=]*= */, "", s)
if [ -n "$pk" ] && [ -n "$ip" ] && [ -n "${key_to_name[$pk]+_}" ]; then pubkey = s
AWG_CLIENT_NAMES["$ip"]="${key_to_name[$pk]}" }
AWG_CLIENT_NAMES["${ip%/32}"]="${key_to_name[$pk]}" /^AllowedIPs/ {
s = $0
sub(/^[^=]*= */, "", s)
ip = s
if (pubkey != "" && ip != "") {
print pubkey "|" ip
}
}')
if [ -n "$conf_peers" ]; then
while IFS='|' read -r pubkey ip; do
if [ -n "$pubkey" ] && [ -n "$ip" ] && [ -n "${key_to_name[$pubkey]+_}" ]; then
local name="${key_to_name[$pubkey]}"
AWG_CLIENT_NAMES["$ip"]="$name"
local bare="${ip%/32}"
AWG_CLIENT_NAMES["$bare"]="$name"
fi fi
done <<< "$peers" done <<< "$conf_peers"
fi fi
return 0
} }
awg_get_name() { awg_get_name() {
@@ -750,7 +822,10 @@ awg_format_label() {
awg_get_client_ips() { awg_get_client_ips() {
AWG_CLIENT_IPS=() AWG_CLIENT_IPS=()
mapfile -t AWG_CLIENT_IPS < <(docker exec "$CONTAINER" sh -c "sed -n 's/^AllowedIPs = \(.*\/32\)$/\1/p' '$AWG_VPN_CONF'" 2>/dev/null | tr -d '\r') mapfile -t AWG_CLIENT_IPS < <(docker exec "$CONTAINER" sh -c "sed -n 's/^AllowedIPs[[:space:]]*=[[:space:]]*\(.*\/32\)[[:space:]]*$/\1/p' '$AWG_VPN_CONF'" 2>/dev/null | tr -d '\r')
if [ "${#AWG_CLIENT_IPS[@]}" -eq 0 ]; then
mapfile -t AWG_CLIENT_IPS < <(docker exec "$CONTAINER" sh -c "awk '/^\[Peer\]/,/^$/' '$AWG_VPN_CONF' | sed -n 's/^AllowedIPs[[:space:]]*=[[:space:]]*//p'" 2>/dev/null | tr -d '\r' | grep '/32')
fi
} }
awg_add_clients_ssh() { awg_add_clients_ssh() {
@@ -890,47 +965,52 @@ awg_patch_start_sh() {
[ -z "${AWG_START_SH:-}" ] && return [ -z "${AWG_START_SH:-}" ] && return
docker exec "$CONTAINER" sh -c "[ -f /opt/amnezia/start.sh.final-backup ] || cp '$AWG_START_SH' /opt/amnezia/start.sh.final-backup" 2>/dev/null docker exec "$CONTAINER" sh -c "[ -f /opt/amnezia/start.sh.final-backup ] || cp '$AWG_START_SH' /opt/amnezia/start.sh.final-backup" 2>/dev/null
local block="${AWG_MARKER_BEGIN} local warp_block=""
" warp_block+="${AWG_MARKER_BEGIN}"$'\n'
block+="if [ -f '${AWG_WARP_CONF}' ]; then wg-quick up '${AWG_WARP_CONF}' || true; fi warp_block+=""$'\n'
" warp_block+="if [ -f '${AWG_WARP_CONF}' ]; then"$'\n'
warp_block+=" wg-quick up '${AWG_WARP_CONF}' || true"$'\n'
warp_block+="fi"$'\n'
warp_block+=""$'\n'
if [ ${#AWG_SELECTED_IPS[@]} -gt 0 ]; then if [ ${#AWG_SELECTED_IPS[@]} -gt 0 ]; then
block+="ip route add default dev warp table 100 2>/dev/null || ip route replace default dev warp table 100 2>/dev/null || true warp_block+="ip route add default dev warp table 100 2>/dev/null || ip route replace default dev warp table 100 2>/dev/null || true"$'\n'
" warp_block+=""$'\n'
local prio=100 local prio=100
for ip in "${AWG_SELECTED_IPS[@]}"; do for ip in "${AWG_SELECTED_IPS[@]}"; do
block+="ip rule add from ${ip} table 100 priority ${prio} 2>/dev/null || true warp_block+="ip rule add from ${ip} table 100 priority ${prio} 2>/dev/null || true"$'\n'
" warp_block+="iptables -t nat -C POSTROUTING -s ${ip} -o warp -j MASQUERADE 2>/dev/null || iptables -t nat -I POSTROUTING 1 -s ${ip} -o warp -j MASQUERADE"$'\n'
block+="iptables -t nat -C POSTROUTING -s ${ip} -o warp -j MASQUERADE 2>/dev/null || iptables -t nat -I POSTROUTING 1 -s ${ip} -o warp -j MASQUERADE
"
((prio++)) ((prio++))
done done
fi fi
block+="${AWG_MARKER_END}"
warp_block+=""$'\n'
warp_block+="${AWG_MARKER_END}"
docker exec "$CONTAINER" sh -c " docker exec "$CONTAINER" sh -c "
if grep -qF '${AWG_MARKER_BEGIN}' '$AWG_START_SH' 2>/dev/null; then if grep -qF '${AWG_MARKER_BEGIN}' '$AWG_START_SH'; then
sed -i '/${AWG_MARKER_BEGIN//\//\\/}/,/${AWG_MARKER_END//\//\\/}/d' '$AWG_START_SH' sed -i '/# --- WARP-MANAGER BEGIN ---/,/# --- WARP-MANAGER END ---/d' '$AWG_START_SH'
fi fi
" 2>/dev/null " 2>/dev/null
docker exec "$CONTAINER" sh -c " docker exec "$CONTAINER" sh -c "
if grep -qF 'tail -f /dev/null' '$AWG_START_SH'; then if grep -qF 'tail -f /dev/null' '$AWG_START_SH'; then
tmpf=\$(mktemp) tmpfile=\$(mktemp)
while IFS= read -r line; do while IFS= read -r line; do
if echo \"\$line\" | grep -qF 'tail -f /dev/null'; then if echo \"\$line\" | grep -qF 'tail -f /dev/null'; then
cat <<'WBLOCK' cat <<'WARPBLOCK'
${block} ${warp_block}
WBLOCK WARPBLOCK
fi fi
echo \"\$line\" echo \"\$line\"
done < '$AWG_START_SH' > \"\$tmpf\" done < '$AWG_START_SH' > \"\$tmpfile\"
mv \"\$tmpf\" '$AWG_START_SH'; chmod +x '$AWG_START_SH' mv \"\$tmpfile\" '$AWG_START_SH'
chmod +x '$AWG_START_SH'
else else
cat >> '$AWG_START_SH' <<'WBLOCK' cat >> '$AWG_START_SH' <<'WARPBLOCK'
${block} ${warp_block}
WBLOCK WARPBLOCK
chmod +x '$AWG_START_SH' chmod +x '$AWG_START_SH'
fi fi
" 2>/dev/null " 2>/dev/null
@@ -940,7 +1020,7 @@ awg_remove_from_start_sh() {
[ -z "${AWG_START_SH:-}" ] && return [ -z "${AWG_START_SH:-}" ] && return
docker exec "$CONTAINER" sh -c " docker exec "$CONTAINER" sh -c "
if grep -qF '${AWG_MARKER_BEGIN}' '$AWG_START_SH' 2>/dev/null; then if grep -qF '${AWG_MARKER_BEGIN}' '$AWG_START_SH' 2>/dev/null; then
sed -i '/${AWG_MARKER_BEGIN//\//\\/}/,/${AWG_MARKER_END//\//\\/}/d' '$AWG_START_SH' sed -i '/# --- WARP-MANAGER BEGIN ---/,/# --- WARP-MANAGER END ---/d' '$AWG_START_SH'
fi fi
" 2>/dev/null " 2>/dev/null
} }