Documentation

When ports 443 and 80 are taken

Run HyperDrop at home beside a website, DSM or Home Assistant that already uses your router's web ports.

Contents

Why this happens

Your router forwards by port number only: port 443 goes to one device. It cannot read the name in a link, so it cannot send share.example.com to HyperDrop and photos.example.com to your NAS.

HyperDrop always needs port 443 (HTTPS: every link, and its certificates). Port 80 is needed for a free hyperdrop.link address, whose approval check arrives there; with your own domain it only carries plain http:// visitors over to HTTPS.

If nothing else uses those ports, forward 443 to HyperDrop's HTTPS port (5443 on a Synology NAS) and 80 to its HTTP port (5080), and skip this page.

The fix: one proxy that routes by name

Forward ports 443 and 80 to a small proxy that sends each name to the right place. For HTTPS the proxy must pass the encrypted connection through unopened: it reads only the name the browser asks for, and HyperDrop keeps its own certificates.

Passed through, every connection reaches HyperDrop from the proxy's address. So on port 443 the proxy also sends a PROXY header naming the visitor, and you tell HyperDrop the proxy's address (below) so it believes that header from the proxy alone. Needs HyperDrop Server 1.2.1 or newer.

Not supported: proxies that decrypt the traffic and forward it on, such as DSM's own Reverse Proxy (Login Portal, Advanced), Nginx Proxy Manager's proxy hosts or a plain Caddy reverse_proxy. HyperDrop issues its certificates through port 443 itself and treats its two names as separate security origins, so it must receive the connection as the browser sent it.

Whatever proxy you use, it needs three rules. Replace share.example.com with your domain, and the addresses with your own.

PortWhat arrivesSend it to
443your domain, files. your domain, or no name at all (someone typed the bare public IP)HyperDrop's HTTPS port, passed through, with the PROXY header
80your domain, files. your domain, or the bare public IPHyperDrop's HTTP port, with no PROXY header
botheverything elseyour other service

Keep the bare-IP rules with your own domain too: HyperDrop's port check reaches your server by its public IP, and a free hyperdrop.link address needs them before its name exists (HyperDrop Desktop signs in at https://<your public IP>, and the address service checks http://<your public IP>).

Never send the PROXY header on port 80 or to your other service: neither expects it, and both refuse the connection.

Your other service sees the proxy, not the visitor: every visitor arrives from the proxy's address (127.0.0.1 for a proxy on the NAS). DSM's Auto Block and sign-in protection then see all visitors as one client and cannot tell a stranger guessing passwords from you. Do not expose DSM's sign-in through this route; use QuickConnect or a VPN.

HAProxy

Proxy at 192.168.1.10, HyperDrop at 192.168.1.20, the other service at 192.168.1.30. To run the proxy on the NAS itself, see the next section.

defaults
    timeout connect 5s
    timeout client  1h
    timeout server  1h

# Port 443: route by the name the browser asks for, without decrypting.
frontend https_in
    bind :443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }
    use_backend hyperdrop_https if { req.ssl_sni -i share.example.com files.share.example.com }
    # A connection to the bare public IP carries no name.
    use_backend hyperdrop_https if !{ req.ssl_sni -m found }
    default_backend other_https

backend hyperdrop_https
    mode tcp
    # send-proxy-v2: tell HyperDrop the visitor's address.
    server nas 192.168.1.20:5443 send-proxy-v2

backend other_https
    mode tcp
    server other 192.168.1.30:443

# Port 80: route by the Host header.
frontend http_in
    bind :80
    mode http
    acl hyperdrop_name req.hdr(host),field(1,:) -i share.example.com files.share.example.com
    acl bare_ip        req.hdr(host),field(1,:) -m reg ^[0-9.]+$
    use_backend hyperdrop_http if hyperdrop_name or bare_ip
    default_backend other_http

backend hyperdrop_http
    mode http
    server nas 192.168.1.20:5080

backend other_http
    mode http
    server other 192.168.1.30:80

The one-hour timeouts keep long transfers alive. End the file with a line break: HAProxy 3 refuses one without ("Missing LF on last line").

On the Synology NAS itself, next to DSM

When DSM's own web server holds the NAS's ports 80 and 443, run HAProxy in Container Manager (Docker on DSM 6) on two free ports and point the router at those:

  1. Router: forward public 443 to the NAS port 8443, and public 80 to the NAS port 8080.
  2. Save the HAProxy configuration above as /volume1/docker/haproxy/haproxy.cfg with three changes: bind :8443 and bind :8080 instead of 443 and 80, HyperDrop at 127.0.0.1:5443 (keep send-proxy-v2) and 127.0.0.1:5080, and the other service at 127.0.0.1:443 and 127.0.0.1:80 (DSM's own web server).
  3. Start it with host networking (so 127.0.0.1 is the NAS). Over SSH:
sudo docker run -d --name hyperdrop-proxy --restart unless-stopped --network host \
  -v /volume1/docker/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \
  haproxy:lts

The proxy's address for HyperDrop (below) is then 127.0.0.1. If your model has no Container Manager or Docker package, run the proxy on another always-on machine.

nginx

Port 443 uses the stream module, which passes the connection through. nginx sends the PROXY header per server block, not per destination, so the other site's connections take one internal hop on 127.0.0.1 that strips it. If this same nginx serves your other site on 443, move that site to another port (8443, say) and point the internal hop's proxy_pass at it.

# Port 443: route by the name the browser asks for, without decrypting.
stream {
    map $ssl_preread_server_name $https_backend {
        share.example.com        192.168.1.20:5443;
        files.share.example.com  192.168.1.20:5443;
        ""                       192.168.1.20:5443;   # bare public IP: no name
        default                  127.0.0.1:10444;
    }
    server {
        listen 443;
        ssl_preread on;
        proxy_pass $https_backend;
        proxy_protocol on;   # tell HyperDrop the visitor's address
    }
    # Your other service: remove the header, so it gets the connection as before.
    server {
        listen 127.0.0.1:10444 proxy_protocol;
        proxy_pass 192.168.1.30:443;
    }
}

# Port 80: route by the Host header.
http {
    server {
        listen 80;
        server_name share.example.com files.share.example.com ~^[0-9.]+$;
        location / {
            proxy_pass http://192.168.1.20:5080;
            proxy_set_header Host $host;
        }
    }
    server {
        listen 80 default_server;
        location / {
            proxy_pass http://192.168.1.30:80;
            proxy_set_header Host $host;
        }
    }
}

Traefik

Add these to a file provider. Your existing HTTP routers keep working; HyperDrop's names and connections with no name pass through to HyperDrop.

tcp:
  routers:
    hyperdrop:
      entryPoints: [websecure]
      rule: "HostSNI(`share.example.com`) || HostSNI(`files.share.example.com`)"
      service: hyperdrop
      tls:
        passthrough: true
    hyperdrop-bare-ip:
      entryPoints: [websecure]
      rule: "HostSNI(`*`)"
      priority: 1
      service: hyperdrop
      tls:
        passthrough: true
  services:
    hyperdrop:
      loadBalancer:
        serversTransport: hyperdrop
        servers: [{ address: "192.168.1.20:5443" }]
  serversTransports:
    hyperdrop:
      # Tell HyperDrop the visitor's address.
      proxyProtocol:
        version: 2
http:
  routers:
    hyperdrop-http:
      entryPoints: [web]
      rule: "Host(`share.example.com`) || Host(`files.share.example.com`) || HostRegexp(`^[0-9]{1,3}([.][0-9]{1,3}){3}$`)"
      service: hyperdrop-http
  services:
    hyperdrop-http:
      loadBalancer:
        servers: [{ url: "http://192.168.1.20:5080" }]

This is Traefik 3.5 or newer. On 3.4 or older, leave out serversTransports and the service's serversTransport line, and put proxyProtocol: { version: 2 } inside the service's loadBalancer instead. On port 80, HostRegexp matches the bare public IP, so your other sites keep every path of their own.

A redirect to HTTPS on the web entry point (static configuration) runs before any router, so the port 80 routes above never see a request. Move that redirect into a middleware on your own routers.

Tell HyperDrop the proxy's address

Without this, every visitor reaches HyperDrop from the proxy's address, so they all count as one person: one visitor's wrong guesses at a share password lock everyone out of password-protected shares for 12 hours, and wrong sign-in guesses lock everyone out of signing in. The two lockouts are separate.

Do this together with the PROXY header. List the address the proxy connects from: 192.168.1.10 here, 127.0.0.1 for a proxy on the NAS, several separated by commas. Once listed, the proxy must send the header on HTTPS or is refused, and HyperDrop refuses the header from anyone not listed, so no visitor can claim another's address.

List the proxy's single address, not your whole network (not 192.168.1.0/24): every listed device can claim any visitor address.

Synology NAS, new install

In the install wizard, fill in Proxy address (optional).

Synology NAS, already installed

Over SSH, add one line to hyperdrop.conf (or change its existing HYPERDROP_TRUSTED_PROXIES line), then stop and run the package in Package Center.

# DSM 7
echo 'HYPERDROP_TRUSTED_PROXIES="192.168.1.10"' | sudo tee -a /var/packages/hyperdrop/var/hyperdrop.conf
# DSM 6 (use the volume HyperDrop is installed on)
echo 'HYPERDROP_TRUSTED_PROXIES="192.168.1.10"' | sudo tee -a /volume1/@appdata/hyperdrop/hyperdrop.conf

Linux

Add a systemd override, not a line in /etc/hyperdrop/server.env (reinstalling rewrites that file):

sudo systemctl edit hyperdrop

and enter:

[Service]
Environment=HYPERDROP_TRUSTED_PROXIES=192.168.1.10

then sudo systemctl restart hyperdrop.

If HyperDrop does not start, its log names the address it could not read.

Check it works

  1. Forward the router's public 443 and 80 to the proxy (or to the NAS ports it listens on).
  2. Tell HyperDrop the proxy's address (above).
  3. In HyperDrop Desktop, open Servers, the server, then Domain & Connectivity, and press Check & update DNS (Run DNS & HTTPS checks when you manage the DNS records yourself). The server has the HyperDrop address service reach it from the internet and warns when port 443 or 80 does not arrive or lands on another device.
  4. Open one of your other sites to confirm it still works.

If it does not work

Links stop opening

HyperDrop's log names the address that connected, for example:

http: TLS handshake error from 172.17.0.2:51234: proxyproto: upstream connection sent PROXY header but isn't allowed to send one

That address sent the header but is not listed: list it. proxyproto: proxy protocol signature not present is the reverse: listed, but not sending the header. A proxy container on a bridge network connects from its bridge address (often 172.17.0.x), not 127.0.0.1, which is why the NAS recipe uses host networking.

Links answer "not found" in one browser

If your other service's certificate (*.example.com) also covers your HyperDrop name (share.example.com), a browser already connected to one of your other sites reuses that connection for HyperDrop links. Those requests never reach HyperDrop. Keep the HyperDrop name outside the wildcard: give your other sites their own certificates, or use a name one level deeper, such as share.home.example.com. A free hyperdrop.link address and the files. name are never affected.

No forward works at all

A server behind carrier-grade NAT (your ISP shares one public address between many homes) cannot receive any forward, proxy or not; HyperDrop says so on the Domain screen. Ask your ISP for a public IP address, or install HyperDrop on a VPS: see Carrier-grade NAT.