Skip to content

Fix postgresql hostaddr semantics - #4102

Closed
mbj wants to merge 3 commits into
transact-rs:mainfrom
mbj:fix/hostaddr-semantics
Closed

mbj wants to merge 3 commits into
transact-rs:mainfrom
mbj:fix/hostaddr-semantics

Conversation

@mbj

@mbj mbj commented Nov 12, 2025 •

Copy link
Copy Markdown
Contributor
  • Before hostaddr was used to just be an alternative way to set host. But this is not how libpq actually behaves or intents hostaddr to be used.
  • Instead hostaddr is meant to contain a numeric IP address to connect to, bypassing DNS lookups. This can be useful if the DNS lookups are slow, or if the DNS lookup has to be bypassed as the port is proxied to localhost for ifrastructure reasons. The TLS verification is still always done against the host parameter. Basically it allows to do verify-full on proxied ports.

Libpq docs:

https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS

Does your PR solve an issue?

Yes but issue was not reported yet, the original implementation of hostaddr parameters only misleading/bad semantics.

Is this a breaking change?

Can be argued both ways. Its definitively a bugfix, but could be that the bug is loadbearing. I'm fine either way, going to use a fork till release.

@mbj
mbj force-pushed the fix/hostaddr-semantics branch 3 times, most recently from 743da8b to df9a233 Compare November 12, 2025 19:02
@mbj
mbj force-pushed the fix/hostaddr-semantics branch 3 times, most recently from 4dcf7d1 to 96a356c Compare November 12, 2025 19:10
* Since 3.x extensions in the CSR are not automatically carried
* Needed as rustls does not use the CN to verify hostnames it uses
  subject alternative DNS names only.
@mbj
mbj force-pushed the fix/hostaddr-semantics branch from 96a356c to 207c342 Compare November 12, 2025 21:52
Comment thread tests/certs/server.crt
25iUuef8MB8GA1UdIwQYMBaAFAsNqVaRis9sZCI21R2IdC583ZFuMAUGAytlcANB
AKyosmZvuCIrWkvb4QN8k2Fwf09LICCNjh571XwNxp9eUEEwJOjl956o6SFxDlgK
Cr1llASvz5cPm6jUV2wlaQc=
-----END CERTIFICATE-----

@mbj mbj Nov 12, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            b6:c7:1f:4b:11:c0:a1:8f
        Signature Algorithm: ED25519
        Issuer: C=us, ST=california, O=Internet Widgits Pty Ltd, CN=Austin Bonander
        Validity
            Not Before: Jul  1 05:21:56 2025 GMT
            Not After : Jun 29 05:21:56 2035 GMT
        Subject: C=us, ST=california, O=SQLx.rs, CN=sqlx.rs
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    0d:f7:4b:6a:ac:aa:96:6c:b1:47:18:ae:99:5e:31:
                    70:e3:e7:f9:a1:6f:9e:87:3d:a3:b7:08:82:20:63:
                    97:3c
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                3D:4A:67:F7:91:87:16:E3:1E:EF:ED:A9:1B:9A:DB:98:94:B9:E7:FC
            X509v3 Authority Key Identifier:
                0B:0D:A9:56:91:8A:CF:6C:64:22:36:D5:1D:88:74:2E:7C:DD:91:6E
    Signature Algorithm: ED25519
    Signature Value:
        13:11:0e:cd:af:48:ad:27:21:a1:0b:35:37:03:f1:7c:27:5f:
        5c:c1:e2:5e:9b:20:31:38:43:ba:28:3e:f6:16:ae:5b:e6:f5:
        2a:50:51:dd:97:96:f0:03:88:c1:ac:cc:85:db:2d:04:53:a1:
        ba:66:96:3d:0f:f0:64:d5:24:0a

After:

$ openssl x509 -text -noout -in server.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2c:da:80:96:d8:8e:10:fe:5f:79:0a:e3:20:15:d8:03:a6:02:d1:f5
        Signature Algorithm: ED25519
        Issuer: C=us, ST=california, O=Internet Widgits Pty Ltd, CN=Austin Bonander
        Validity
            Not Before: Nov 12 21:49:58 2025 GMT
            Not After : Nov 10 21:49:58 2035 GMT
        Subject: C=us, ST=california, O=SQLx.rs, CN=sqlx.rs
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    0d:f7:4b:6a:ac:aa:96:6c:b1:47:18:ae:99:5e:31:
                    70:e3:e7:f9:a1:6f:9e:87:3d:a3:b7:08:82:20:63:
                    97:3c
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:sqlx.rs
            X509v3 Subject Key Identifier:
                3D:4A:67:F7:91:87:16:E3:1E:EF:ED:A9:1B:9A:DB:98:94:B9:E7:FC
            X509v3 Authority Key Identifier:
                0B:0D:A9:56:91:8A:CF:6C:64:22:36:D5:1D:88:74:2E:7C:DD:91:6E
    Signature Algorithm: ED25519
    Signature Value:
        ac:a8:b2:66:6f:b8:22:2b:5a:4b:db:e1:03:7c:93:61:70:7f:
        4f:4b:20:20:8d:8e:1e:7b:d5:7c:0d:c6:9f:5e:50:41:30:24:
        e8:e5:f7:9e:a8:e9:21:71:0e:58:0a:0a:bd:65:94:04:af:cf:
        97:0f:9b:a8:d4:57:6c:25:69:07

Note the subject alternative name is now present (was absent before)!

Comment thread tests/certs/README.md Resolved
@mbj
mbj force-pushed the fix/hostaddr-semantics branch from 1d469ca to b3c90e1 Compare November 12, 2025 22:11
@mbj
mbj marked this pull request as ready for review November 12, 2025 22:11
Comment thread sqlx-postgres/src/options/mod.rs Resolved
None => net::connect_tcp(&options.host, options.port, MaybeUpgradeTls(options)).await?,
None => {
net::connect_tcp(
options.host_addr.as_ref().unwrap_or(&options.host),

@mbj mbj Nov 12, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified the integration tests to cover this behavior, they now:

  • instruct the ssl tests to connect to a host: sqlx.rs that does not resolve to a postgresql instance on the public DNS.
  • but provide the hostaddr to point it to 127.0.0.1 bypassing DNS lookups
  • proof that cert validation fully works in this scenario in upgrading to verify-full from verify-ca.

I use sqlx.rs as hostname for this test as this is the hostname present in the test certificates.

* Before hostaddr was used to just be an alternative way to set `host`.
  But this is not how libpq actually behaves or intents hostaddr to be
  used.
* Instead `hostaddr` is meant to contain a numeric IP address to connect
  to, bypassing DNS lookups. This can be useful if the DNS lookups are
  slow, or if the DNS lookup has to be bypassed as the port is proxied
  to localhost for ifrastructure reasons. The TLS verification is still
  always done against the `host` parameter. Basically it allows to do
  `verify-full` on proxied ports.
@mbj
mbj force-pushed the fix/hostaddr-semantics branch from b3c90e1 to f795fe9 Compare November 13, 2025 00:32

@abonander abonander left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me, but it now has merge conflicts that need to be resolved. Sorry for taking so long to get to this.

I think there's also some value in keeping the existing integration test behavior, so it might be better to make the verify-full test an additional step in the same job.

@farazdagi

Copy link
Copy Markdown

I'm interested in helping move this forward.

@mbj are you planning to address the remaining review feedback yourself? If you'd like help, I could send a PR targeting your branch, or prepare a replacement PR against upstream (that preserves your work and attribution), whichever you prefer.

@abonander

Copy link
Copy Markdown
Collaborator

I ended up going with a slightly different approach in #4514:

  • It makes no sense to accept &str for hostaddr when it's internally required to be an IpAddr.
  • I kept the verify-ca step and added a separate verify-full step.
  • I changed test TLS certificates to be generated on-the-fly instead of being checked-in so it's easier to modify their parameters and we don't have to worry about expiration or misuse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants