This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Install necessary packages
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
openvpn \
|
||||||
|
squid \
|
||||||
|
curl \
|
||||||
|
bash \
|
||||||
|
iptables \
|
||||||
|
ip6tables \
|
||||||
|
net-tools \
|
||||||
|
procps \
|
||||||
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
RUN mkdir -p /etc/openvpn /var/log/squid /var/cache/squid /var/run/squid
|
||||||
|
|
||||||
|
# Copy configuration files
|
||||||
|
COPY squid.conf /etc/squid/squid.conf
|
||||||
|
COPY start.sh /start.sh
|
||||||
|
COPY version /version
|
||||||
|
|
||||||
|
# Make scripts executable
|
||||||
|
RUN chmod +x /start.sh
|
||||||
|
|
||||||
|
# Expose proxy port
|
||||||
|
EXPOSE 3128
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
ENV PROXY_URL=""
|
||||||
|
ENV VPN_CONFIG=""
|
||||||
|
ENV VPN_TYPE="openvpn"
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:3128/ || exit 1
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
CMD ["/start.sh"]
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
# VPN Proxy Docker Container
|
||||||
|
|
||||||
|
A Docker container that creates a proxy server routed through a VPN connection (OpenVPN or WireGuard). This allows you to access websites through a VPN tunnel by using the container as a proxy.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Supports both OpenVPN (.ovpn) and WireGuard (.conf) configurations
|
||||||
|
- Squid proxy server for HTTP/HTTPS traffic
|
||||||
|
- Automatic VPN connection and health monitoring
|
||||||
|
- Configurable target URL for testing
|
||||||
|
- Health checks and automatic restart on failure
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Docker with `--cap-add=NET_ADMIN` capability
|
||||||
|
- Access to `/dev/net/tun` device (for OpenVPN)
|
||||||
|
- VPN configuration file (.ovpn or .conf)
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
1. **Build the container:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t vpn-proxy .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Run with OpenVPN:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name vpn-proxy \
|
||||||
|
--cap-add=NET_ADMIN \
|
||||||
|
--device /dev/net/tun \
|
||||||
|
-p 3128:3128 \
|
||||||
|
-e PROXY_URL=https://example.com \
|
||||||
|
-e VPN_CONFIG=/vpn/config.ovpn \
|
||||||
|
-e VPN_TYPE=openvpn \
|
||||||
|
-v /path/to/your/config.ovpn:/vpn/config.ovpn:ro \
|
||||||
|
vpn-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Run with WireGuard:**
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name vpn-proxy \
|
||||||
|
--cap-add=NET_ADMIN \
|
||||||
|
-p 3128:3128 \
|
||||||
|
-e PROXY_URL=https://example.com \
|
||||||
|
-e VPN_CONFIG=/vpn/wg0.conf \
|
||||||
|
-e VPN_TYPE=wireguard \
|
||||||
|
-v /path/to/your/wg0.conf:/vpn/wg0.conf:ro \
|
||||||
|
vpn-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
| Variable | Required | Default | Description |
|
||||||
|
| ------------ | -------- | --------- | ---------------------------------- |
|
||||||
|
| `PROXY_URL` | Yes | - | Target URL to proxy through VPN |
|
||||||
|
| `VPN_CONFIG` | Yes | - | Path to VPN configuration file |
|
||||||
|
| `VPN_TYPE` | No | `openvpn` | VPN type: `openvpn` or `wireguard` |
|
||||||
|
|
||||||
|
### Using the Proxy
|
||||||
|
|
||||||
|
Once the container is running, you can use it as a proxy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test the proxy
|
||||||
|
curl -x localhost:3128 https://httpbin.org/ip
|
||||||
|
|
||||||
|
# Use in applications
|
||||||
|
export http_proxy=http://localhost:3128
|
||||||
|
export https_proxy=http://localhost:3128
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
vpn-proxy:
|
||||||
|
build: .
|
||||||
|
container_name: vpn-proxy
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun
|
||||||
|
ports:
|
||||||
|
- "3128:3128"
|
||||||
|
environment:
|
||||||
|
- PROXY_URL=https://example.com
|
||||||
|
- VPN_CONFIG=/vpn/config.ovpn
|
||||||
|
- VPN_TYPE=openvpn
|
||||||
|
volumes:
|
||||||
|
- ./config.ovpn:/vpn/config.ovpn:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
### OpenVPN Configuration
|
||||||
|
|
||||||
|
Your `.ovpn` file should contain all necessary connection details including:
|
||||||
|
|
||||||
|
- Server address and port
|
||||||
|
- Authentication credentials
|
||||||
|
- Certificate data
|
||||||
|
- Cipher settings
|
||||||
|
|
||||||
|
### WireGuard Configuration
|
||||||
|
|
||||||
|
Your `.conf` file should follow the standard WireGuard format:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = your_private_key
|
||||||
|
Address = 10.0.0.2/24
|
||||||
|
DNS = 8.8.8.8
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = server_public_key
|
||||||
|
Endpoint = server.example.com:51820
|
||||||
|
AllowedIPs = 0.0.0.0/0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
The container includes health checks and will automatically restart if:
|
||||||
|
|
||||||
|
- VPN connection is lost
|
||||||
|
- Proxy server stops responding
|
||||||
|
- Container receives SIGTERM/SIGINT
|
||||||
|
|
||||||
|
Check logs with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs vpn-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- The container runs with `NET_ADMIN` capability to manage network interfaces
|
||||||
|
- VPN credentials are stored in mounted configuration files
|
||||||
|
- The proxy server is configured to forward all traffic through the VPN
|
||||||
|
- No caching is performed to ensure fresh data through VPN
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
1. **VPN won't connect:**
|
||||||
|
|
||||||
|
- Check that the configuration file is properly mounted
|
||||||
|
- Verify VPN credentials and server availability
|
||||||
|
- Check container logs for specific error messages
|
||||||
|
|
||||||
|
2. **Proxy not working:**
|
||||||
|
|
||||||
|
- Ensure port 3128 is accessible
|
||||||
|
- Test with `curl -x localhost:3128 http://httpbin.org/ip`
|
||||||
|
- Check that the VPN connection is active
|
||||||
|
|
||||||
|
3. **Permission denied:**
|
||||||
|
- Ensure the container has `--cap-add=NET_ADMIN`
|
||||||
|
- For OpenVPN, ensure `/dev/net/tun` is accessible
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is open source and available under the MIT License.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# VPN Proxy Environment Variables
|
||||||
|
|
||||||
|
# Target URL to proxy (required)
|
||||||
|
# This is the website you want to access through the VPN
|
||||||
|
PROXY_URL=https://example.com
|
||||||
|
|
||||||
|
# VPN Configuration file path (required)
|
||||||
|
# Mount your .ovpn or .conf file and specify the path here
|
||||||
|
VPN_CONFIG=/vpn/config.ovpn
|
||||||
|
|
||||||
|
# VPN Type (optional, defaults to openvpn)
|
||||||
|
# Options: openvpn, wireguard
|
||||||
|
VPN_TYPE=openvpn
|
||||||
|
|
||||||
|
# Example usage:
|
||||||
|
# docker run -d \
|
||||||
|
# --name vpn-proxy \
|
||||||
|
# --cap-add=NET_ADMIN \
|
||||||
|
# --device /dev/net/tun \
|
||||||
|
# -p 3128:3128 \
|
||||||
|
# -e PROXY_URL=https://example.com \
|
||||||
|
# -e VPN_CONFIG=/vpn/config.ovpn \
|
||||||
|
# -e VPN_TYPE=openvpn \
|
||||||
|
# -v /path/to/your/config.ovpn:/vpn/config.ovpn:ro \
|
||||||
|
# vpn-proxy
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Squid configuration for VPN proxy
|
||||||
|
http_port 3128
|
||||||
|
|
||||||
|
# Allow access from any IP (since we're in a container)
|
||||||
|
acl localnet src 0.0.0.1-0.255.255.255
|
||||||
|
acl localnet src 10.0.0.0/8
|
||||||
|
acl localnet src 100.64.0.0/10
|
||||||
|
acl localnet src 169.254.0.0/16
|
||||||
|
acl localnet src 172.16.0.0/12
|
||||||
|
acl localnet src 192.168.0.0/16
|
||||||
|
acl localnet src fc00::/7
|
||||||
|
acl localnet src fe80::/10
|
||||||
|
|
||||||
|
# Allow all HTTP and HTTPS traffic
|
||||||
|
acl SSL_ports port 443
|
||||||
|
acl Safe_ports port 80
|
||||||
|
acl Safe_ports port 21
|
||||||
|
acl Safe_ports port 443
|
||||||
|
acl Safe_ports port 70
|
||||||
|
acl Safe_ports port 210
|
||||||
|
acl Safe_ports port 1025-65535
|
||||||
|
acl Safe_ports port 280
|
||||||
|
acl Safe_ports port 488
|
||||||
|
acl Safe_ports port 591
|
||||||
|
acl Safe_ports port 777
|
||||||
|
acl CONNECT method CONNECT
|
||||||
|
|
||||||
|
# Deny requests to certain unsafe ports
|
||||||
|
http_access deny !Safe_ports
|
||||||
|
|
||||||
|
# Deny CONNECT to other than secure SSL ports
|
||||||
|
http_access deny CONNECT !SSL_ports
|
||||||
|
|
||||||
|
# Allow localhost management
|
||||||
|
http_access allow localhost manager
|
||||||
|
http_access deny manager
|
||||||
|
|
||||||
|
# Allow access from local networks
|
||||||
|
http_access allow localnet
|
||||||
|
http_access allow localhost
|
||||||
|
|
||||||
|
# Allow all other traffic (since we're proxying through VPN)
|
||||||
|
http_access allow all
|
||||||
|
|
||||||
|
# Cache settings (minimal for proxy)
|
||||||
|
cache_dir ufs /var/cache/squid 100 16 256
|
||||||
|
maximum_object_size 1024 MB
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
access_log /var/log/squid/access.log squid
|
||||||
|
cache_log /var/log/squid/cache.log
|
||||||
|
|
||||||
|
# Don't forward private IPs
|
||||||
|
never_direct allow all
|
||||||
|
|
||||||
|
# Forward all requests through the VPN interface
|
||||||
|
forwarded_for off
|
||||||
|
via off
|
||||||
|
|
||||||
|
# Hide client IP
|
||||||
|
forwarded_for delete
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to log messages
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if VPN is connected
|
||||||
|
check_vpn() {
|
||||||
|
if [ "$VPN_TYPE" = "openvpn" ]; then
|
||||||
|
# Check if tun interface exists and has an IP
|
||||||
|
if ip addr show tun0 >/dev/null 2>&1; then
|
||||||
|
TUN_IP=$(ip addr show tun0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1)
|
||||||
|
if [ -n "$TUN_IP" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif [ "$VPN_TYPE" = "wireguard" ]; then
|
||||||
|
# Check if wg interface exists and has an IP
|
||||||
|
if ip addr show wg0 >/dev/null 2>&1; then
|
||||||
|
WG_IP=$(ip addr show wg0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1)
|
||||||
|
if [ -n "$WG_IP" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to start OpenVPN
|
||||||
|
start_openvpn() {
|
||||||
|
log "Starting OpenVPN with config: $VPN_CONFIG"
|
||||||
|
|
||||||
|
if [ ! -f "$VPN_CONFIG" ]; then
|
||||||
|
log "ERROR: VPN config file not found: $VPN_CONFIG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start OpenVPN in background
|
||||||
|
openvpn --config "$VPN_CONFIG" --daemon --log /var/log/openvpn.log
|
||||||
|
|
||||||
|
# Wait for VPN to connect
|
||||||
|
log "Waiting for VPN connection..."
|
||||||
|
for i in {1..30}; do
|
||||||
|
if check_vpn; then
|
||||||
|
log "VPN connected successfully"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
log "ERROR: VPN failed to connect within 60 seconds"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to start WireGuard
|
||||||
|
start_wireguard() {
|
||||||
|
log "Starting WireGuard with config: $VPN_CONFIG"
|
||||||
|
|
||||||
|
if [ ! -f "$VPN_CONFIG" ]; then
|
||||||
|
log "ERROR: WireGuard config file not found: $VPN_CONFIG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start WireGuard
|
||||||
|
wg-quick up "$VPN_CONFIG"
|
||||||
|
|
||||||
|
# Wait for WireGuard to connect
|
||||||
|
log "Waiting for WireGuard connection..."
|
||||||
|
for i in {1..30}; do
|
||||||
|
if check_vpn; then
|
||||||
|
log "WireGuard connected successfully"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
log "ERROR: WireGuard failed to connect within 60 seconds"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to setup routing
|
||||||
|
setup_routing() {
|
||||||
|
log "Setting up routing for VPN proxy"
|
||||||
|
|
||||||
|
# Get the VPN interface IP
|
||||||
|
if [ "$VPN_TYPE" = "openvpn" ]; then
|
||||||
|
VPN_IP=$(ip addr show tun0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1)
|
||||||
|
VPN_INTERFACE="tun0"
|
||||||
|
elif [ "$VPN_TYPE" = "wireguard" ]; then
|
||||||
|
VPN_IP=$(ip addr show wg0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1)
|
||||||
|
VPN_INTERFACE="wg0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "VPN Interface: $VPN_INTERFACE, IP: $VPN_IP"
|
||||||
|
|
||||||
|
# Set up iptables rules to route traffic through VPN
|
||||||
|
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination $VPN_IP:80
|
||||||
|
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination $VPN_IP:443
|
||||||
|
|
||||||
|
# Allow traffic through VPN interface
|
||||||
|
iptables -A OUTPUT -o $VPN_INTERFACE -j ACCEPT
|
||||||
|
iptables -A INPUT -i $VPN_INTERFACE -j ACCEPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to start Squid proxy
|
||||||
|
start_squid() {
|
||||||
|
log "Starting Squid proxy server"
|
||||||
|
|
||||||
|
# Initialize Squid cache
|
||||||
|
squid -z -N -d 1
|
||||||
|
|
||||||
|
# Start Squid
|
||||||
|
squid -N -d 1 &
|
||||||
|
SQUID_PID=$!
|
||||||
|
|
||||||
|
# Wait for Squid to start
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
if kill -0 $SQUID_PID 2>/dev/null; then
|
||||||
|
log "Squid proxy started successfully on port 3128"
|
||||||
|
else
|
||||||
|
log "ERROR: Failed to start Squid proxy"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to test proxy
|
||||||
|
test_proxy() {
|
||||||
|
log "Testing proxy connection"
|
||||||
|
|
||||||
|
# Test if we can reach the target URL through the proxy
|
||||||
|
if [ -n "$PROXY_URL" ]; then
|
||||||
|
log "Testing connection to: $PROXY_URL"
|
||||||
|
if curl -x localhost:3128 --connect-timeout 10 --max-time 30 -s -o /dev/null "$PROXY_URL"; then
|
||||||
|
log "Proxy test successful - can reach $PROXY_URL"
|
||||||
|
else
|
||||||
|
log "WARNING: Proxy test failed - cannot reach $PROXY_URL"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
log "Starting VPN Proxy container"
|
||||||
|
|
||||||
|
# Check required environment variables
|
||||||
|
if [ -z "$PROXY_URL" ]; then
|
||||||
|
log "ERROR: PROXY_URL environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$VPN_CONFIG" ]; then
|
||||||
|
log "ERROR: VPN_CONFIG environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Configuration:"
|
||||||
|
log " PROXY_URL: $PROXY_URL"
|
||||||
|
log " VPN_CONFIG: $VPN_CONFIG"
|
||||||
|
log " VPN_TYPE: ${VPN_TYPE:-openvpn}"
|
||||||
|
|
||||||
|
# Start VPN based on type
|
||||||
|
if [ "$VPN_TYPE" = "wireguard" ]; then
|
||||||
|
start_wireguard
|
||||||
|
else
|
||||||
|
start_openvpn
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup routing
|
||||||
|
setup_routing
|
||||||
|
|
||||||
|
# Start Squid proxy
|
||||||
|
start_squid
|
||||||
|
|
||||||
|
# Test proxy
|
||||||
|
test_proxy
|
||||||
|
|
||||||
|
log "VPN Proxy is ready and listening on port 3128"
|
||||||
|
log "Use this container as a proxy: http://localhost:3128"
|
||||||
|
|
||||||
|
# Keep container running and monitor
|
||||||
|
while true; do
|
||||||
|
if ! check_vpn; then
|
||||||
|
log "ERROR: VPN connection lost, restarting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! kill -0 $SQUID_PID 2>/dev/null; then
|
||||||
|
log "ERROR: Squid proxy died, restarting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 30
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle shutdown
|
||||||
|
cleanup() {
|
||||||
|
log "Shutting down VPN Proxy"
|
||||||
|
if [ -n "$SQUID_PID" ]; then
|
||||||
|
kill $SQUID_PID 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$VPN_TYPE" = "wireguard" ] && [ -f "$VPN_CONFIG" ]; then
|
||||||
|
wg-quick down "$VPN_CONFIG" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up signal handlers
|
||||||
|
trap cleanup SIGTERM SIGINT
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1.0.0
|
||||||
Reference in New Issue
Block a user