How I build a VPN-Protected Socks5 Proxy
Running a Kubernetes cluster on Raspberry Pis using K3s is a fantastic way to build a powerful and flexible home lab environment. When combined with Portainer for managing your Kubernetes deployments, it becomes even easier to deploy and manage your applications. Recently, I set up a Socks5 proxy that routes all its traffic through a VPN on my K3s cluster, and I want to share the steps I took to accomplish this.
My Setup
Here's a quick overview of the setup I used:
- Hardware: A cluster of three Raspberry Pis running K3s.
- Management: Portainer installed on top of the K3s cluster for easy management of Kubernetes resources.
- Goal: Deploy a Socks5 proxy using the
serjs/go-socks5-proxy
image, ensuring all its traffic is routed through a VPN provided by theqmcgaw/gluetun
container.
Step 1: Creating the Kubernetes Deployment
First, I created a Kubernetes Deployment that included both the Gluetun VPN and the Socks5 proxy containers. Since both containers needed to share the same network namespace to ensure that all traffic from the proxy is routed through the VPN, I configured them to run within the same Pod.
Here’s the YAML file I used:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vpn-proxy
labels:
app: vpn-proxy
spec:
replicas: 1
selector:
matchLabels:
app: vpn-proxy
template:
metadata:
labels:
app: vpn-proxy
spec:
containers:
- name: gluetun
image: qmcgaw/gluetun
ports:
- containerPort: 8080
env:
- name: VPN_SERVICE_PROVIDER
value: "protonvpn"
- name: VPN_TYPE
value: "wireguard"
- name: WIREGUARD_PRIVATE_KEY
value: "{hidden}"
- name: SERVER_COUNTRIES
value: "Netherlands"
- name: VPN_PORT_FORWARDING_PROVIDER
value: "protonvpn"
securityContext:
capabilities:
add: ["NET_ADMIN"]
- name: socks5-proxy
image: serjs/go-socks5-proxy:latest
ports:
- containerPort: 1080
securityContext:
capabilities:
add: ["NET_ADMIN"]
env:
- name: PROXY_UPSTREAM
value: "http://localhost:8080" # Use localhost to route traffic through Gluetun
Explanation
- Single Pod with Multiple Containers: Both the Gluetun VPN and Socks5 proxy run in the same Pod, allowing them to share the same network namespace. This setup simplifies routing, as the Socks5 proxy can send its traffic through the VPN by referencing
localhost
. - Environment Variables: I configured the Gluetun container using environment variables to connect to a ProtonVPN server via WireGuard. I replaced
{hidden}
with my actual WireGuard private key.
Step 2: Exposing the Socks5 Proxy
To make the Socks5 proxy accessible, I exposed it via a Kubernetes Service. Here’s the service configuration I used:
apiVersion: v1
kind: Service
metadata:
name: socks5-proxy-service
spec:
selector:
app: vpn-proxy
ports:
- protocol: TCP
port: 1080
targetPort: 1080
type: LoadBalancer
Explanation
- Service Type: I used the
LoadBalancer
service type to expose the Socks5 proxy externally. On K3s, this service type exposes the proxy on the IP addresses of all the nodes in the cluster. - Port Configuration: The service listens on port 1080, which is the standard port for Socks5 proxies.
Step 3: Deploying via Portainer
With the YAML configurations ready, I used Portainer to deploy them to my K3s cluster. Here’s how I did it:
- Accessing Portainer: I logged into my Portainer instance.
- Deploying: I used Portainer's 'Custom template' feature to upload and deploy the YAML file to my K3s cluster.
Portainer handled the deployment, ensuring that the Pods and Services were correctly set up on my Raspberry Pi cluster.
Step 4: Verifying the Deployment
After deploying the setup, I verified that everything was working as expected:
- Checking the Pods: I used Portainer to check the status of the Pods, ensuring that both the Gluetun and Socks5 proxy containers were running within the same Pod.
- Viewing Logs: I reviewed the logs of the Gluetun container directly in Portainer to confirm that the VPN connection was successfully established.
- Testing Connectivity: I connected to the Socks5 proxy using the external IP address provided by the service. All traffic routed through the proxy was securely tunneled through the VPN.
Conclusion
Setting up a VPN-protected Socks5 proxy on a Raspberry Pi K3s cluster using Portainer was straightforward and effective. By running both the Gluetun and Socks5 proxy containers in the same Pod, I was able to ensure that all outgoing traffic from the proxy was routed securely through the VPN.
Next Steps
- Scaling: I plan to explore scaling this setup to handle more traffic or provide redundancy.
- Security: Adding authentication to the Socks5 proxy is on my to-do list to prevent unauthorized access.
- Monitoring: Setting up monitoring tools to track the performance and availability of my VPN-protected proxy service will be the next step in optimizing my setup.
This setup has provided me with a secure, flexible, and private network service that runs efficiently on my Raspberry Pi cluster, all managed conveniently through Portainer.