diff --git a/qbittorrent/rootfs/etc/s6-overlay/s6-rc.d/svc-qbittorrent/run b/qbittorrent/rootfs/etc/s6-overlay/s6-rc.d/svc-qbittorrent/run index 6e00130b4e..b99392d0a5 100644 --- a/qbittorrent/rootfs/etc/s6-overlay/s6-rc.d/svc-qbittorrent/run +++ b/qbittorrent/rootfs/etc/s6-overlay/s6-rc.d/svc-qbittorrent/run @@ -5,123 +5,23 @@ WEBUI_PORT=${WEBUI_PORT:-8080} export PATH="/usr/local/sbin:/usr/local/bin:${PATH}" -# Global variable used by WireGuard bring-up helper -output="" +# --- New helper: get public IP with rate-limiting fallbacks --- +_get_public_ip() { + local ip + ip=$( + curl -fsS --max-time 10 https://ifconfig.co/ip \ + || curl -fsS --max-time 10 https://api64.ipify.org \ + || curl -fsS --max-time 10 https://ipecho.net/plain + ) || return 1 + + printf '%s\n' "${ip}" +} if bashio::config.true 'silent'; then sed -i 's|/proc/1/fd/1 hassio;|off;|g' /etc/nginx/nginx.conf fi -# -# --- Shared helpers: IP + country with rate-limit fallback, leak monitor --- -# - -_fetch_public_ip() { - # Try several providers; any HTTP error (incl. 429) makes curl -f fail, - # so we fall back to the next one. - local resp - local url - - for url in \ - "https://ifconfig.co/ip" \ - "https://api64.ipify.org" \ - "https://ipecho.net/plain" - do - resp=$(curl -fsS --max-time 10 "${url}" 2>/dev/null || true) - resp="${resp//[[:space:]]/}" - if [[ -n "${resp}" ]]; then - printf '%s\n' "${resp}" - return 0 - fi - done - - return 1 -} - -_fetch_country_code() { - # Same idea for country ISO code. - local resp - local url - - for url in \ - "https://ifconfig.co/country-iso" \ - "https://ipinfo.io/country" - do - resp=$(curl -fsS --max-time 10 "${url}" 2>/dev/null || true) - resp="${resp//[[:space:]]/}" - if [[ -n "${resp}" ]]; then - printf '%s\n' "${resp}" - return 0 - fi - done - - return 1 -} - -_vpn_monitor_public_ip() { - # Arg1: label ("OpenVPN", "WireGuard", etc.) - local vpn_label="${1:-VPN}" - local current_ip_file="/currentip" - local baseline_ip - local vpn_ip - local country - local interval - local initial_delay - - interval=${VPN_LEAK_CHECK_INTERVAL:-300} - initial_delay=${VPN_LEAK_INITIAL_DELAY:-60} - - if ! command -v curl >/dev/null 2>&1; then - bashio::log.warning "${vpn_label}: curl not found; VPN leak monitoring disabled." - return 0 - fi - - if ! bashio::fs.file_exists "${current_ip_file}"; then - bashio::log.warning "${vpn_label}: baseline IP file ${current_ip_file} not found; VPN leak monitoring disabled." - return 0 - fi - - baseline_ip="$(tr -d '[:space:]' < "${current_ip_file}")" - if [[ -z "${baseline_ip}" ]]; then - bashio::log.warning "${vpn_label}: baseline IP in ${current_ip_file} is empty; VPN leak monitoring disabled." - return 0 - fi - - bashio::log.info "${vpn_label}: baseline (non-VPN) IP for leak detection: ${baseline_ip}" - bashio::log.debug "${vpn_label}: waiting ${initial_delay}s before first leak check." - sleep "${initial_delay}" - - while true; do - vpn_ip="$(_fetch_public_ip || true)" - if [[ -z "${vpn_ip}" ]]; then - bashio::log.warning "${vpn_label}: failed to obtain VPN public IP from all providers (rate limited or unreachable)." - else - if country="$(_fetch_country_code || true)"; then - bashio::log.info "${vpn_label}: public IP: ${vpn_ip} (${country})." - else - bashio::log.info "${vpn_label}: public IP: ${vpn_ip} (country unknown)." - fi - - if [[ "${vpn_ip}" == "${baseline_ip}" ]]; then - bashio::log.error "${vpn_label}: VPN leak detected: public IP ${vpn_ip} matches baseline ${baseline_ip}. Stopping add-on." - # Try to terminate the service tree cleanly. - s6-svscanctl -t /var/run/s6/services 2>/dev/null || true - exit 1 - fi - fi - - sleep "${interval}" - done -} - -# -# --- Main logic: OpenVPN / WireGuard / qBittorrent --- -# - if bashio::config.true 'openvpn_enabled'; then - # Start leak monitor for OpenVPN in the background - _vpn_monitor_public_ip "OpenVPN" & - exec /usr/sbin/openvpn \ --config /config/openvpn/config.ovpn \ --script-security 2 \ @@ -155,7 +55,6 @@ else local legacy_bin_dir="${WIREGUARD_STATE_DIR}/iptables-legacy-bin" mkdir -p "${legacy_bin_dir}" - local cmd for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do if command -v "${cmd}-legacy" >/dev/null 2>&1; then ln -sf "$(command -v "${cmd}-legacy")" "${legacy_bin_dir}/${cmd}" @@ -169,11 +68,13 @@ else _wireguard_up_with_iptables_fallback() { local config_path="$1" - local status=0 + local status - output="$(wg-quick up "${config_path}" 2>&1)" || status=$? + output="" + output=$(wg-quick up "${config_path}" 2>&1) + status=$? - if [ "${status}" -eq 0 ]; then + if [ "$status" -eq 0 ]; then return 0 fi @@ -181,7 +82,8 @@ else if command -v iptables-legacy >/dev/null 2>&1 || command -v ip6tables-legacy >/dev/null 2>&1; then wg-quick down "${config_path}" >/dev/null 2>&1 || true _wireguard_prepare_iptables_legacy - output="$(wg-quick up "${config_path}" 2>&1)" || status=$? + output=$(wg-quick up "${config_path}" 2>&1) + status=$? else bashio::log.warning 'iptables errors detected but iptables-legacy binaries are unavailable in the image.' status=1 @@ -196,10 +98,9 @@ else bashio::log.warning "First attempt output:${bashio::constants.LF}${output}" ipv4_config="${WIREGUARD_STATE_DIR}/${wireguard_interface}-ipv4.conf" - : > "${ipv4_config}" + echo -n > "${ipv4_config}" chmod 600 "${ipv4_config}" 2>/dev/null || true - local line endpoint endpoint_host endpoint_port while IFS= read -r line; do if [[ "${line}" =~ ^Endpoint ]]; then endpoint="${line#Endpoint = }" @@ -239,6 +140,14 @@ else bashio::log.info "WireGuard interface ${wireguard_interface} is up." + # Example usage of the helper: get VPN-protected IP and store it + if vpn_ip="$(_get_public_ip)"; then + echo "${vpn_ip}" > /vpn_ip + bashio::log.info "Detected VPN public IP: ${vpn_ip}" + else + bashio::log.warning 'Unable to determine VPN public IP (all IP services failed).' + fi + # Refresh DNS resolver configuration if resolvconf is present if command -v resolvconf >/dev/null 2>&1; then bashio::log.info 'Refreshing DNS resolver configuration via resolvconf -u.' @@ -248,9 +157,6 @@ else else bashio::log.debug 'resolvconf not found in PATH; skipping DNS refresh.' fi - - # Start VPN leak monitor for WireGuard in background - _vpn_monitor_public_ip "WireGuard" & fi if bashio::config.true 'silent'; then