Using Google OAuth to ssh into my server
TL;DR
I put an experimental SSH3 server on a separate hostname, kept my normal SSH v2 behind Cloudflare Tunnel, and logged in with Google using OpenID Connect. SSH3 runs over HTTP/3 on UDP 443, supports a secret URL path, and can mint certs with Let’s Encrypt. If your traffic goes through Cloudflare, use a DNS-only record or Spectrum for UDP.
Why I tried this
SSH3 maps the good parts of SSH onto HTTP/3 with QUIC and TLS 1.3. It has faster session setup and modern auth like OAuth 2.0 and OpenID Connect. Sounds fun for a weekend hack, so I tried it on a throwaway hostname and a spare Dell OptiPlex loaded up with Proxmox and an Ubuntu 24.04 VM.
My setup notes
Separate hostname: I created
h3.shambu.party
with Cloudflare DNS set to DNS-only. That lets UDP 443 reach my box directly. If you must stay proxied, Spectrum is the way to carry UDP (not free).Secret path: SSH3 can hide behind an unguessable URL path. Port scans just see a boring 404. I used a long random slug. This is defense in depth, not a password.
Certs: I let SSH3 generate and renew a public cert with Let’s Encrypt using the built-in flag. You can also point it at an existing cert.
Google login: Client has a tiny
oidc_config.json
. Server checks~/.ssh3/authorized_identities
for your email tied to the Google issuer. Works cleanly.
Gotchas I hit
UDP 443 matters: QUIC rides on UDP. If your ISP or firewall blocks it, you will stare at timeouts. Open UDP 443 using ufw or similar.
Cloudflare Tunnel: Tunnels do not deliver custom UDP to your origin. Use a DNS-only record for your SSH3 hostname or use Spectrum to proxy UDP.
Still experimental: Treat SSH3 like a lab project, not production. Keep SSH v2 around and use a separate host.
How to set up OAuth with SSH3
Installation
You can build with Go or grab release binaries:
go install github.com/francoismichel/ssh3/cmd/...@latest
# or clone + build
git clone https://github.com/francoismichel/ssh3
cd ssh3
go build -o ssh3 cmd/ssh3/main.go
CGO_ENABLED=1 go build -o ssh3-server cmd/ssh3-server/main.go
The README documents both paths and the flags shown above.
Install on both the client and the server.
Server setup
On the server, with a secret path and public cert:
ssh3-server \
-bind 0.0.0.0:443 \
-generate-public-cert h3.shambu.party \
-url-path /ssh3-my-super-long-random-secret
Create ~/.ssh3/authorized_identities
:
oidc <your_client_id> https://accounts.google.com <your_email@gmail.com>
Now from the client, with Google OpenID Connect:
ssh3 -use-oidc https://accounts.google.com \
-oidc-config ~/.ssh3/oidc_config.json \
shambu@h3.shambu.party/ssh3-my-super-long-random-secret
You should see your Google OAuth screen open in a browser window.
After authorizing, you should be inside the server.
Quick SSH2 vs SSH3 numbers
What to expect: SSH3 is designed to cut round trips during session setup, so new sessions should start faster. Throughput during long transfers is not the goal yet and may be lower than OpenSSH right now. The project itself calls out “faster for session establishment, not throughput,” estimating SSHv2 takes about 5 to 7 RTTs vs about 3 RTTs for SSH3. The paper also measured port-forward throughput and found OpenSSH higher for TCP, while SSH3 uniquely supports UDP forwarding.
1) Measure connection setup time
I used hyperfine
to time a trivially short command on each client. This captures DNS plus TCP or QUIC handshakes plus auth.
# install hyperfine
brew install hyperfine # macOS
# or: sudo apt-get install hyperfine # Debian/Ubuntu
hyperfine -w 5 -r 50 \
'ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new you@h2.shambu.party "true"'
hyperfine -w 5 -r 50 \
'ssh3 -privkey <path_to_private_key> you@h3.shambu.party/ssh3-my-super-long-random-secret "true"'
Tip:
- Use key auth on both to isolate the transport. If you keep Google OIDC, do one interactive login, then measure cached runs only.
Why this matters: SSH3 rides HTTP/3 over QUIC with TLS 1.3, which can complete the TLS handshake in 1-RTT and piggyback the CONNECT that starts your session. That reduces the startup round trips compared to TCP plus SSHv2’s transport and user-auth dance.
My testing
Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
---|---|---|---|---|
ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new you@h2.shambu.party "true" |
312.0 ± 24.5 | 248.0 | 392.4 | 4.07 ± 0.87 |
ssh3 -privkey <path_to_private_key> you@h3.shambu.party/ssh3-my-super-long-random-secret "true" |
76.7 ± 15.2 | 53.9 | 141.4 | 1.00 |
Session establishment is 4.07 ± 0.87 times faster.
Takeaways
What you gain with SSH3: It keeps the familiar SSH connection model, but runs over HTTP/3 on QUIC, which cuts the number of round trips during session setup and makes logins feel snappier. You can authenticate with OAuth 2.0 or OpenID Connect, use normal X.509 certs for the server, and even stick the service behind a secret URL path that looks like a 404 to random scans. On top of TCP forwarding, you also get UDP forwarding, plus QUIC perks like connection migration and upcoming multipath, which opens doors for tunneling DNS or other UDP apps. It is still experimental, so keep it on a side host and do not replace your main SSH just yet. This was a nice little experiment.
References
SSH3 repo and its README for HTTP/3, QUIC, OIDC, secret paths, and flags.
IETF draft and paper for background.
Cloudflare docs about UDP and Spectrum.