Setting up one of these is a real pain in the neck. You follow some guide on the Internet and it never works. This one won't either, but hopefully it'll get you somewhere closer to success.
- shadowsocks-libev server with v2ray plugin Shadowsocks over websocket to work with cloudflare and disguise as normal traffic
- CloudFlare Proxies requests and hides the ip of our vm instance
- Google Cloud Platform GCP is offering a one year trial with $300 worth of credits.
- Caddy Go http server
- Podman Daemon-less docker replacement
Starting with setting up the server, I chose the CentOS 8 image because ENTERPRISE, so I ended up with outdated packages. With GCP, you first need to allocate a static external ip address and SSH keys via the web console. GCP has its own firewall, so things like netcat also requires additional rules. Make sure to allow http and https ingress by tagging the instance with http and https. Additionally, don't be an idiot and associate the SSH key with the wrong username (the part before the @).
Onto the machine. Install docker(podman), and since we're using CentOS, everything is outdated, and it doesn't even have Caddy.
sudo yum install docker
curl https://getcaddy.com | bash -s personal tls.dns.cloudflare
Now, set up everything related to Caddy
sudo adduser -r -d /var/www -s /sbin/nologin caddy
mkdir /var/www
sudo mkdir /var/www
sudo mkdir /etc/caddy
sudo chown -R root:caddy /etc/caddy
sudo touch /etc/caddy/Caddyfile
sudo mkdir /etc/ssl/caddy
sudo chown -R caddy:root /etc/ssl/caddy
sudo chmod 770 /etc/ssl/caddy
sudo chown caddy:caddy /var/www
sudo curl -s https://raw.githubusercontent.com/mholt/caddy/master/dist/init/linux-systemd/caddy.service -o /etc/systemd/system/caddy.service
Thank you Digitalocean for providing a guide on Caddy. Now edit /etc/systemd/system/caddy.service and change the user and group to caddy. We may also uncomment the commented out options without knowing what they do.
At this point, we move on to setting up firewalld on our GCP vm instance.
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
sudo firewall-cmd --set-default-zone=public
sudo firewall-cmd --permanent --add-port=22/tcp
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --zone=trusted --add-interface=docker0
sudo firewall-cmd --permanent --zone=public --add-masquerade
And verify that everything is setup
sudo firewall-cmd --permanent --list-all-zones
Then reload our firewalld config
sudo firewall-cmd --reload
Now that most things are ready to go, we can work on our actual shadowsocks server. Have the following files ready:
/etc/caddy/Caddyfile
# make sure to have an A record in cloudflare for this domain name
# with the proxy light on
my.domain.name {
proxy /ws 127.0.0.1:10001 {
without /ws
websocket
header_upstream -Origin
}
tls {
dns cloudflare
}
}
~/start.sh
#!/bin/bash
docker run \
-d \
--dns 8.8.8.8 \
--dns 8.8.4.4 \
-p 127.0.0.1:10001:1080 \
-e PASSWORD=super-amazing-password-here \
-e ARGS='-v -d 8.8.8.8' \
--name ss \
mazy/ss-v2ray:v3.3.3-1.2.0
/etc/systemd/system/caddy.service
# to make caddy use the letsencrypt staging server
# add the following arguments to the arguments passed to the caddy binary
# so that if we mess up our dns configuration, letsencrypt won't throttle us
-ca https://acme-staging-v02.api.letsencrypt.org/directory
# add the following environment variables
# the global api key can be found under My Profile > API Tokens
Environment=CLOUDFLARE_EMAIL=MY_CLOUDFLARE_EMAIL
Environment=CLOUDFLARE_API_KEY=GLOBAL_API_KEY
Finally, let's start Caddy
sudo systemctl daemon-reload
sudo systemctl enable caddy
sudo systemctl start caddy
After a bit, let's check on it with
sudo systemctl status caddy
If everything is good, we can remove the staging server argument added earlier, restart caddy, and proceed to start our docker container with
sudo ~/start.sh
And we can check on it with
sudo docker logs ss
I copied my beautiful client configuration from the docker image github page:
{
"server":"my.domain.name",
"server_port":443,
"local_address":"0.0.0.0",
"local_port":1080,
"password":"that-password-you-entered-earlier",
"method":"chacha20-ietf-poly1305",
"fast_open":true,
"plugin":"/usr/local/bin/v2ray-plugin",
"plugin_opts":"path=/ws;host=my.domain.name;tls"
}
Which I lovingly run with
ss-local -v -c ./ss.json
Optionally, privoxy config here:
listen-address 127.0.0.1:8118
forward-socks5 / 127.0.0.1:1080 .
Issues:
- If caddy fails to start with 203 Permission Denied, it might be SELinux. I don't know how to use it, but this command resets its context, whatever that means.
sudo restorecon -v /usr/local/bin/caddy