rwadurian/backend/mpc-system/scripts/tproxy.sh

346 lines
11 KiB
Bash

#!/bin/bash
#
# Transparent Proxy Script for Gateway (192.168.1.100)
# Routes traffic from LAN clients (192.168.1.111) through Clash proxy
#
# Usage:
# ./tproxy.sh on # Enable transparent proxy
# ./tproxy.sh off # Disable transparent proxy
# ./tproxy.sh status # Check status
#
# Prerequisites:
# - Clash running with allow-lan: true
# - This machine is the gateway for 192.168.1.111
#
set -e
# ============================================
# Configuration
# ============================================
# Clash proxy ports
CLASH_HTTP_PORT="${CLASH_HTTP_PORT:-7890}"
CLASH_SOCKS_PORT="${CLASH_SOCKS_PORT:-7891}"
CLASH_REDIR_PORT="${CLASH_REDIR_PORT:-7892}"
CLASH_TPROXY_PORT="${CLASH_TPROXY_PORT:-7893}"
CLASH_DNS_PORT="${CLASH_DNS_PORT:-1053}"
# Network configuration
LAN_INTERFACE="${LAN_INTERFACE:-eth0}"
LAN_SUBNET="${LAN_SUBNET:-192.168.1.0/24}"
GATEWAY_IP="${GATEWAY_IP:-192.168.1.100}"
# Clients to proxy (space-separated)
PROXY_CLIENTS="${PROXY_CLIENTS:-192.168.1.111}"
# Bypass destinations (don't proxy these)
BYPASS_IPS="127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4"
# iptables chain name
CHAIN_NAME="CLASH_TPROXY"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# ============================================
# Check Prerequisites
# ============================================
check_root() {
if [ "$EUID" -ne 0 ]; then
log_error "This script must be run as root"
exit 1
fi
}
check_clash() {
# Check for any clash process (clash, clash-linux-amd64, etc.)
if ! pgrep -f "clash" > /dev/null 2>&1; then
log_error "Clash is not running"
log_info "Please start Clash first"
exit 1
fi
# Check if Clash is listening on redir port
if ! ss -tlnp | grep -q ":$CLASH_REDIR_PORT"; then
log_warn "Clash redir port ($CLASH_REDIR_PORT) not listening"
log_info "Make sure your Clash config has:"
echo " redir-port: $CLASH_REDIR_PORT"
echo " allow-lan: true"
fi
}
# ============================================
# Enable Transparent Proxy
# ============================================
enable_tproxy() {
check_root
check_clash
log_info "Enabling transparent proxy..."
# Enable IP forwarding
log_info "Enabling IP forwarding..."
echo 1 > /proc/sys/net/ipv4/ip_forward
sysctl -w net.ipv4.ip_forward=1 > /dev/null
# Make IP forwarding persistent
if ! grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf; then
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
fi
# Create NAT chain for transparent proxy
log_info "Creating iptables rules..."
# Remove existing rules if any
iptables -t nat -D PREROUTING -j $CHAIN_NAME 2>/dev/null || true
iptables -t nat -F $CHAIN_NAME 2>/dev/null || true
iptables -t nat -X $CHAIN_NAME 2>/dev/null || true
# Create new chain
iptables -t nat -N $CHAIN_NAME
# Bypass local and private networks
for ip in $BYPASS_IPS; do
iptables -t nat -A $CHAIN_NAME -d $ip -j RETURN
done
# Bypass traffic to this gateway itself
iptables -t nat -A $CHAIN_NAME -d $GATEWAY_IP -j RETURN
# Only proxy traffic from specified clients
for client in $PROXY_CLIENTS; do
log_info "Adding proxy rule for client: $client"
# Redirect HTTP/HTTPS traffic to Clash redir port
iptables -t nat -A $CHAIN_NAME -s $client -p tcp --dport 80 -j REDIRECT --to-ports $CLASH_REDIR_PORT
iptables -t nat -A $CHAIN_NAME -s $client -p tcp --dport 443 -j REDIRECT --to-ports $CLASH_REDIR_PORT
# Redirect all other TCP traffic
iptables -t nat -A $CHAIN_NAME -s $client -p tcp -j REDIRECT --to-ports $CLASH_REDIR_PORT
done
# Apply the chain to PREROUTING
iptables -t nat -A PREROUTING -j $CHAIN_NAME
# Setup DNS redirect (optional - redirect DNS to Clash DNS)
if ss -ulnp | grep -q ":$CLASH_DNS_PORT"; then
log_info "Setting up DNS redirect to Clash DNS..."
for client in $PROXY_CLIENTS; do
iptables -t nat -A PREROUTING -s $client -p udp --dport 53 -j REDIRECT --to-ports $CLASH_DNS_PORT
done
fi
# Ensure MASQUERADE for forwarded traffic
iptables -t nat -A POSTROUTING -s $LAN_SUBNET -o $LAN_INTERFACE -j MASQUERADE 2>/dev/null || true
log_info "Transparent proxy enabled!"
log_info ""
log_info "Proxied clients: $PROXY_CLIENTS"
log_info "Clash redir port: $CLASH_REDIR_PORT"
log_info ""
log_info "Test from client (192.168.1.111):"
log_info " curl -I https://www.google.com"
}
# ============================================
# Disable Transparent Proxy
# ============================================
disable_tproxy() {
check_root
log_info "Disabling transparent proxy..."
# Remove DNS redirect rules
for client in $PROXY_CLIENTS; do
iptables -t nat -D PREROUTING -s $client -p udp --dport 53 -j REDIRECT --to-ports $CLASH_DNS_PORT 2>/dev/null || true
done
# Remove the chain from PREROUTING
iptables -t nat -D PREROUTING -j $CHAIN_NAME 2>/dev/null || true
# Flush and delete the chain
iptables -t nat -F $CHAIN_NAME 2>/dev/null || true
iptables -t nat -X $CHAIN_NAME 2>/dev/null || true
log_info "Transparent proxy disabled!"
log_info ""
log_info "Clients will now access internet directly (through NAT only)"
}
# ============================================
# Check Status
# ============================================
show_status() {
echo ""
echo "============================================"
echo "Transparent Proxy Status"
echo "============================================"
echo ""
# Check IP forwarding
echo "IP Forwarding:"
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" = "1" ]; then
echo -e " Status: ${GREEN}Enabled${NC}"
else
echo -e " Status: ${RED}Disabled${NC}"
fi
echo ""
# Check Clash
echo "Clash Process:"
if pgrep -f "clash" > /dev/null 2>&1; then
echo -e " Status: ${GREEN}Running${NC}"
echo " PID: $(pgrep -f clash | head -1)"
else
echo -e " Status: ${RED}Not Running${NC}"
fi
echo ""
# Check Clash ports
echo "Clash Ports:"
echo -n " HTTP ($CLASH_HTTP_PORT): "
ss -tlnp | grep -q ":$CLASH_HTTP_PORT" && echo -e "${GREEN}Listening${NC}" || echo -e "${RED}Not Listening${NC}"
echo -n " SOCKS ($CLASH_SOCKS_PORT): "
ss -tlnp | grep -q ":$CLASH_SOCKS_PORT" && echo -e "${GREEN}Listening${NC}" || echo -e "${RED}Not Listening${NC}"
echo -n " Redir ($CLASH_REDIR_PORT): "
ss -tlnp | grep -q ":$CLASH_REDIR_PORT" && echo -e "${GREEN}Listening${NC}" || echo -e "${RED}Not Listening${NC}"
echo -n " DNS ($CLASH_DNS_PORT): "
ss -ulnp | grep -q ":$CLASH_DNS_PORT" && echo -e "${GREEN}Listening${NC}" || echo -e "${RED}Not Listening${NC}"
echo ""
# Check iptables rules
echo "iptables Transparent Proxy Chain:"
if iptables -t nat -L $CHAIN_NAME > /dev/null 2>&1; then
echo -e " Status: ${GREEN}Active${NC}"
echo " Rules:"
iptables -t nat -L $CHAIN_NAME -n --line-numbers 2>/dev/null | head -20
else
echo -e " Status: ${YELLOW}Not Active${NC}"
fi
echo ""
# Check PREROUTING
echo "PREROUTING Chain (first 10 rules):"
iptables -t nat -L PREROUTING -n --line-numbers | head -12
echo ""
}
# ============================================
# Test Proxy from Client
# ============================================
test_proxy() {
echo ""
echo "============================================"
echo "Proxy Test Instructions"
echo "============================================"
echo ""
echo "Run these commands on 192.168.1.111 to test:"
echo ""
echo "1. Test Google (requires proxy):"
echo " curl -I --connect-timeout 5 https://www.google.com"
echo ""
echo "2. Test external IP:"
echo " curl -s https://ipinfo.io/ip"
echo ""
echo "3. Test Docker Hub:"
echo " curl -I --connect-timeout 5 https://registry-1.docker.io/v2/"
echo ""
echo "4. Test GitHub:"
echo " curl -I --connect-timeout 5 https://github.com"
echo ""
}
# ============================================
# Show Required Clash Configuration
# ============================================
show_clash_config() {
echo ""
echo "============================================"
echo "Required Clash Configuration"
echo "============================================"
echo ""
echo "Add these settings to your Clash config.yaml:"
echo ""
cat << 'EOF'
# Enable LAN access
allow-lan: true
bind-address: "*"
# Proxy ports
port: 7890 # HTTP proxy
socks-port: 7891 # SOCKS5 proxy
redir-port: 7892 # Transparent proxy (Linux only)
tproxy-port: 7893 # TProxy port (optional)
# DNS settings (optional but recommended)
dns:
enable: true
listen: 0.0.0.0:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 223.5.5.5
- 119.29.29.29
fallback:
- 8.8.8.8
- 1.1.1.1
EOF
echo ""
echo "After modifying, restart Clash:"
echo " systemctl restart clash"
echo " # or"
echo " killall clash && clash -d /path/to/config &"
echo ""
}
# ============================================
# Main
# ============================================
case "${1:-}" in
on|enable|start)
enable_tproxy
;;
off|disable|stop)
disable_tproxy
;;
status)
show_status
;;
test)
test_proxy
;;
config)
show_clash_config
;;
*)
echo "Transparent Proxy Manager for Clash"
echo ""
echo "Usage: $0 {on|off|status|test|config}"
echo ""
echo "Commands:"
echo " on - Enable transparent proxy for LAN clients"
echo " off - Disable transparent proxy"
echo " status - Show current status"
echo " test - Show test commands for clients"
echo " config - Show required Clash configuration"
echo ""
echo "Environment Variables:"
echo " CLASH_REDIR_PORT - Clash redir port (default: 7892)"
echo " CLASH_DNS_PORT - Clash DNS port (default: 1053)"
echo " LAN_INTERFACE - LAN interface (default: eth0)"
echo " PROXY_CLIENTS - Space-separated client IPs (default: 192.168.1.111)"
echo ""
echo "Example:"
echo " sudo $0 on # Enable with defaults"
echo " sudo PROXY_CLIENTS='192.168.1.111 192.168.1.112' $0 on # Multiple clients"
echo " sudo $0 off # Disable"
echo ""
exit 1
;;
esac