diff --git a/src/internal/mgr/transfersrv.go b/src/internal/mgr/transfersrv.go index 03d15d1..102d2d0 100644 --- a/src/internal/mgr/transfersrv.go +++ b/src/internal/mgr/transfersrv.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "strconv" + "strings" "sync" "time" @@ -91,7 +92,12 @@ type TransferServer struct { // room before pulling gigabytes). The caller owns both files and is responsible // for deleting them. func NewTransferServer(files TransferFiles, host string, port int) (*TransferServer, error) { - if net.ParseIP(host) == nil { + // The host is whatever the operator advertises as this machine's address + // (panel.display_ip, falling back to public_ip): usually an IPv4 literal, + // but a DNS name dials exactly the same. The peer pins the certificate by + // its fingerprint rather than checking a hostname, so the only requirement + // is that the host survives being embedded in a URL. + if host == "" || strings.ContainsAny(host, " \t/?#@:") { return nil, fmt.Errorf("cannot build a transfer address from %q", host) } certPEM, keyPEM, der, err := cert.SelfSigned(host) diff --git a/src/main_transfer.go b/src/main_transfer.go index 3d2acbd..1958ebd 100644 --- a/src/main_transfer.go +++ b/src/main_transfer.go @@ -231,7 +231,7 @@ func transferSend(args []string) error { MetaSHA: manifest.MetaSHA, }, host, port) if err != nil { - return fmt.Errorf("%w (check panel.public_ip — it is the address the other host will dial)", err) + return fmt.Errorf("%w (the address comes from panel.display_ip, falling back to panel.public_ip — it is what the other host will dial)", err) } defer srv.Close()