# k8s/shadowsocks/shadowsocks.yaml # Personal Shadowsocks proxy (for Shadowrocket/other SS clients) — an # alternative tunnel to the WireGuard setup in cluster-config/, useful when # a network blocks/throttles WireGuard but not generic TLS-looking traffic. # # Everything that varies between deployments (port, password, method) lives # in the shadowsocks-config Secret below — the Deployment/Service never # hardcode a value, so re-pointing this at a new port or rotating the # password is a Secret edit + rollout restart, no YAML edit. # # Prerequisites: # talos put cluster/SHADOWSOCKS_PASSWORD SHADOWSOCKS_PASSWORD="$(openssl rand -base64 24)" # talos put cluster/SHADOWSOCKS_PORT SHADOWSOCKS_PORT="8388" # # Apply: # kubectl create namespace vpn --dry-run=client -o yaml | kubectl apply -f - # kubectl -n vpn create secret generic shadowsocks-config \ # --from-literal=SERVER_PORT="$(talos get cluster/SHADOWSOCKS_PORT --key SHADOWSOCKS_PORT)" \ # --from-literal=PASSWORD="$(talos get cluster/SHADOWSOCKS_PASSWORD --key SHADOWSOCKS_PASSWORD)" \ # --from-literal=METHOD="aes-256-gcm" \ # --from-literal=TIMEOUT="300" # kubectl apply -f k8s/shadowsocks/shadowsocks.yaml # # Rotate password (or change port) later: # kubectl -n vpn delete secret shadowsocks-config && # kubectl -n vpn rollout restart deploy/shadowsocks # # Client config: SERVER_PORT/METHOD/PASSWORD above feed directly into the # Shadowrocket/SS client's server, method, and password fields. SERVER_ADDR # for the client is the LB IP below (192.168.1.166), or your router's WAN # address/DDNS hostname (riotpiao.duckdns.org) with port-forwarding to it — # same pattern as the wg1 WireGuard peer in cluster-config/phone_config.conf. apiVersion: v1 kind: Namespace metadata: name: vpn --- apiVersion: apps/v1 kind: Deployment metadata: name: shadowsocks namespace: vpn spec: replicas: 1 selector: matchLabels: app: shadowsocks template: metadata: labels: app: shadowsocks spec: containers: - name: shadowsocks image: shadowsocks/shadowsocks-libev:latest env: - name: SERVER_ADDR value: "0.0.0.0" - name: SERVER_PORT valueFrom: secretKeyRef: name: shadowsocks-config key: SERVER_PORT - name: PASSWORD valueFrom: secretKeyRef: name: shadowsocks-config key: PASSWORD - name: METHOD valueFrom: secretKeyRef: name: shadowsocks-config key: METHOD - name: TIMEOUT valueFrom: secretKeyRef: name: shadowsocks-config key: TIMEOUT # containerPort is informational only (no portRange support for # env-driven SERVER_PORT) — the Service below is what actually # routes traffic, matched on the same Secret key via downward API # isn't available for Service ports, so targetPort uses the literal # port name instead; see Service ports comment. ports: - containerPort: 8388 protocol: TCP - containerPort: 8388 protocol: UDP resources: requests: cpu: 50m memory: 32Mi limits: cpu: 500m memory: 128Mi --- # LoadBalancer via Cilium LB-IPAM (see k8s/cilium/lb-ipam-pool.yaml) — pinned # to .166 so router port-forwarding and the DDNS hostname stay stable across # pod/service recreates, same pattern forgejo uses at .165. # # NOTE: SERVER_PORT in the Secret must match port/targetPort/nodePort here. # If you change the port, update both the Secret and this Service together. apiVersion: v1 kind: Service metadata: name: shadowsocks namespace: vpn annotations: io.cilium/lb-ipam-ips: "192.168.1.166" spec: type: LoadBalancer selector: app: shadowsocks ports: - name: tcp protocol: TCP port: 8388 targetPort: 8388 - name: udp protocol: UDP port: 8388 targetPort: 8388 --- # Restrict egress like the forgejo-runner pattern (k8s/forge/runner.yaml) — # a proxy server is, by design, an open relay to the internet for whoever # holds the password; LAN/pod-network egress is blocked so a compromised # password can't be used to pivot into the cluster or LAN. CoreDNS is # explicitly allowed — shadowsocks-libev resolves client-requested hostnames # itself, so blanket-blocking the service subnet would break that. apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: shadowsocks-egress namespace: vpn spec: podSelector: matchLabels: app: shadowsocks policyTypes: [Egress] egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 - to: - ipBlock: cidr: 0.0.0.0/0 except: - 192.168.1.0/24 - 10.244.0.0/16 - 10.96.0.0/12