Restricting custom domains to specific SSH keys
I am having some trouble setting up custom domains and restricting them to specific SSH keys.
For context this is my setup:
- sish domain:
t.hrsn.net- this is the domain used in the SSH command to connect to sish and is the default hostname when not using a custom domain (e.g.tunnel123.t.hrsn.net). - Custom domain:
t.wdh.gg- this is the domain I'm trying to restrict to a specific SSH key. A CNAME record is configured fort.wdh.ggand*.t.wdh.ggpointing tot.hrsn.net. - Cloudflare proxy is disabled.
- I am using Docker compose to host sish.
In my config file I have the following:
bind-any-host: false
bind-hosts: t.wdh.gg
Now, this config works and I can setup subdomains on t.wdh.gg like tunnel123.t.wdh.gg however even though I have a TXT record set at _sish.t.wdh.gg with the content:
SHA256:yQ2G5ra7npl6ROKw3BJQWULROIG37u14aMfbfKoWFqQ
Even though that TXT record is in place, anyone regardless if they are using that SSH key are able to use t.wdh.gg subdomains even though it should be restricted to that specific key.
I have tried the following, none of which worked:
- Removing the
bind-hostskey entirely, however when attempting to use a subdomain oft.wdh.ggliketunnel123.t.wdh.ggit would instead bind totunnel123.t.wdh.gg.t.hrsn.net. - Removing the
SHA256:bit from the TXT record, which did not work. - Using the old DNS configuration by creating the following TXT record at
t.wdh.gg(attempted with and without theSHA256:bit):
sish=SHA256:yQ2G5ra7npl6ROKw3BJQWULROIG37u14aMfbfKoWFqQ
Please let me know how I can setup custom domains and restrict them using TXT records to specific SSH keys. Thanks!
Hey @antoniomika, no rush, but are you able to look into this? Thanks 😄
Are you using the main branch version? When I have that running and try to bind without the TXT being set to the current key, it will bind to a subdomain instead.
I'm using v2.16.0.
@EpicEric Are you able to share your config and exactly what you put in the TXT record?
The documentation referring to the _sish record is in accordance with this change, which hasn't been released in a tagged version yet. I believe you still need to use sish=SSHFINGERPRINT in your case.
I'm running sish with these options:
# compose.yml
services:
sish:
# ... snip ...
image: docker.io/antoniomika/sish@main
command: |
--ssh-address=:22
--http-address=:80
--https-address=:443
--authentication-keys-directory=/pubkeys
--private-keys-directory=/keys
--https-certificate-directory=/ssl
--https-ondemand-certificate=true
--https-ondemand-certificate-accept-terms=true
[email protected]
--https=true
--force-https=true
--log-to-client=true
--idle-connection=false
--bind-random-aliases=false
--bind-random-ports=false
--bind-random-subdomains=false
--bind-random-subdomains-length=6
--http-load-balancer=true
--tcp-load-balancer=true
--alias-load-balancer=true
--time-format=2006-01-02T15:04:05
--domain=my.domain
I believe the only relevant option is --bind-random-aliases=false.
Even when using the Docker image you are using, no matter whether I'm using the old TXT record or new one, it still allows anyone to bind to it.
This is my full config:
authentication-keys-directory: "/pubkeys"
banned-subdomains: localhost, www
bind-any-host: false
bind-hosts: t.hrsn.dev,t.wdh.gg
bind-random-aliases: false
bind-random-ports: true
bind-random-subdomains: false
bind-random-subdomains-length: 12
domain: "t.hrsn.net"
http-address: "tcp://107.150.46.51:80,tcp6://[2604:4300:a:149::6d96:2e33]:80"
https: true
https-address: "tcp://107.150.46.51:443,tcp6://[2604:4300:a:149::6d96:2e33]:443"
https-certificate-directory: "/ssl"
port-bind-range: 1000-1999
private-keys-directory: "/keys"
redirect-root: true
redirect-root-location: https://hrsn.net/#tunnels
ssh-address: "tcp://107.150.46.51:2222,tcp6://[2604:4300:a:149::6d96:2e33]:2222"
tcp-address: "tcp://107.150.46.51,tcp6://[2604:4300:a:149::6d96:2e33]"
This is my Docker compose file:
services:
sish:
image: antoniomika/sish:main
container_name: sish
volumes:
- /etc/letsencrypt:/etc/letsencrypt
- ./pubkeys:/pubkeys
- ./keys:/keys
- ./ssl:/ssl
- ./config.yml:/config.yml:ro
command: |
--config=/config.yml
network_mode: host
restart: always
A couple questions:
- For the SSH key fingerprint, do we get it from the private key that the user has or do we retrieve it from the public key on the server? I have been using the fingerprint of the private key.
- For the TXT record, do we include the
SHA256:bit or not? - I'm assuming the TXT record goes on the host listed under
bind-hosts, so in my case_sish.t.wdh.gg, is this correct?
- It has to be from either of the user's key. Both generate the same fingerprint:
- Yes.
- Also yes.
A friend who's using sish has run into a similar issue, and --bind-any-hosts fixed it in his case, although the root cause couldn't be determined yet.
Actually, reading on the documentation for --bind-hosts, it seems that you must specify the root host, i.e. "Requested hosts should be subdomains of a host in this list". So perhaps changing your config to bind-hosts: t.hrsn.dev,wdh.gg could do the trick.
A friend who's using sish has run into a similar issue, and
--bind-any-hostsfixed it in his case, although the root cause couldn't be determined yet.
So I should set that option to true and remove the bind-hosts bit?
FYI, I intend to host subdomains on t.wdh.gg, not wdh.gg, (e.g. tunnel123.t.wdh.gg).
You can leave that as is, then.
With the current implementation of verifyDNS, _sish.t.wdh.gg will only apply for t.wdh.gg, not any subdomains. The appropriate TXT entries would have to be added for each subdomain as well.
Going through the code, I believe the option you'll want is force-requested-subdomains: true. This should error when the user doesn't have the appropriate permission to bind to it.
I tried that option with both types of TXT records, and it didn't work, not sure why. I also tried both with and without bind-any-host enabled.
Is it possible that the TXT record verification system is just completely broken?
It definitely works for me, as it doesn't let me bind on a subdomain if the TXT is missing. I'm not really sure what else could be causing this issue, unfortunately.