SMTP falsely prefers IPv4 over IPv6 #328

Closed
opened 2025-10-09 16:22:48 +03:00 by OVERLORD · 11 comments
Owner

Originally created by @imp1sh on GitHub.

Vaultwarden Support String

Your environment (Generated via diagnostics page)

  • Vaultwarden version: v1.32.0-040e2a7b
  • Web-vault version: v2024.6.2c
  • OS/Arch: linux/x86_64
  • Running within a container: true (Base: Debian)
  • Environment settings overridden: true
  • Uses a reverse proxy: true
  • IP Header check: true (X-Real-IP)
  • Internet access: true
  • Internet access via a proxy: false
  • DNS Check: true
  • Browser/Server Time Check: false
  • Server/NTP Time Check: true
  • Domain Configuration Check: true
  • HTTPS Check: true
  • Database type: SQLite
  • Database version: 3.46.0
  • Clients used:
  • Reverse proxy and version:
  • Other relevant information:

Config (Generated via diagnostics page)

Show Running Config

Environment settings which are overridden: DOMAIN, SIGNUPS_ALLOWED, ADMIN_TOKEN, SMTP_HOST, SMTP_SECURITY, SMTP_PORT, SMTP_FROM, SMTP_USERNAME, SMTP_PASSWORD

{
  "_duo_akey": null,
  "_enable_duo": false,
  "_enable_email_2fa": false,
  "_enable_smtp": true,
  "_enable_yubico": true,
  "_icon_service_csp": "",
  "_icon_service_url": "",
  "_ip_header_enabled": true,
  "_max_note_size": 10000,
  "_smtp_img_src": "cid:",
  "admin_ratelimit_max_burst": 3,
  "admin_ratelimit_seconds": 300,
  "admin_session_lifetime": 20,
  "admin_token": "***",
  "allowed_iframe_ancestors": "",
  "attachments_folder": "data/attachments",
  "auth_request_purge_schedule": "30 * * * * *",
  "authenticator_disable_time_drift": false,
  "data_folder": "data",
  "database_conn_init": "",
  "database_max_conns": 10,
  "database_timeout": 30,
  "database_url": "***************",
  "db_connection_retries": 15,
  "disable_2fa_remember": false,
  "disable_admin_token": false,
  "disable_icon_download": false,
  "domain": "*****://*************",
  "domain_origin": "*****://*************",
  "domain_path": "",
  "domain_set": true,
  "duo_context_purge_schedule": "30 * * * * *",
  "duo_host": null,
  "duo_ikey": null,
  "duo_skey": null,
  "duo_use_iframe": false,
  "email_2fa_auto_fallback": false,
  "email_2fa_enforce_on_verified_invite": false,
  "email_attempts_limit": 3,
  "email_change_allowed": true,
  "email_expiration_time": 600,
  "email_token_size": 6,
  "emergency_access_allowed": true,
  "emergency_notification_reminder_schedule": "0 3 * * * *",
  "emergency_request_timeout_schedule": "0 7 * * * *",
  "enable_db_wal": true,
  "enable_websocket": true,
  "enforce_single_org_with_reset_pw_policy": false,
  "event_cleanup_schedule": "0 10 0 * * *",
  "events_days_retain": null,
  "experimental_client_feature_flags": "fido2-vault-credentials",
  "extended_logging": true,
  "helo_name": null,
  "hibp_api_key": null,
  "http_request_block_non_global_ips": true,
  "http_request_block_regex": null,
  "icon_blacklist_non_global_ips": true,
  "icon_blacklist_regex": null,
  "icon_cache_folder": "data/icon_cache",
  "icon_cache_negttl": 259200,
  "icon_cache_ttl": 2592000,
  "icon_download_timeout": 10,
  "icon_redirect_code": 302,
  "icon_service": "internal",
  "incomplete_2fa_schedule": "30 * * * * *",
  "incomplete_2fa_time_limit": 3,
  "increase_note_size_limit": false,
  "invitation_expiration_hours": 120,
  "invitation_org_name": "Vaultwarden",
  "invitations_allowed": true,
  "ip_header": "X-Real-IP",
  "job_poll_interval_ms": 30000,
  "log_file": null,
  "log_level": "info",
  "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f",
  "login_ratelimit_max_burst": 10,
  "login_ratelimit_seconds": 60,
  "org_attachment_limit": null,
  "org_creation_users": "",
  "org_events_enabled": false,
  "org_groups_enabled": false,
  "password_hints_allowed": true,
  "password_iterations": 100000,
  "push_enabled": false,
  "push_identity_uri": "https://identity.bitwarden.com",
  "push_installation_id": "***",
  "push_installation_key": "***",
  "push_relay_uri": "https://push.bitwarden.com",
  "reload_templates": false,
  "require_device_email": false,
  "rsa_key_filename": "data/rsa_key",
  "send_purge_schedule": "0 5 * * * *",
  "sendmail_command": null,
  "sends_allowed": true,
  "sends_folder": "data/sends",
  "show_password_hint": false,
  "signups_allowed": false,
  "signups_domains_whitelist": "",
  "signups_verify": true,
  "signups_verify_resend_limit": 6,
  "signups_verify_resend_time": 3600,
  "smtp_accept_invalid_certs": false,
  "smtp_accept_invalid_hostnames": false,
  "smtp_auth_mechanism": null,
  "smtp_debug": false,
  "smtp_embed_images": true,
  "smtp_explicit_tls": null,
  "smtp_from": "********************",
  "smtp_from_name": "Vaultwarden - Password Tresor",
  "smtp_host": "********************",
  "smtp_password": "***",
  "smtp_port": 587,
  "smtp_security": "starttls",
  "smtp_ssl": true,
  "smtp_timeout": 15,
  "smtp_username": "*********************",
  "templates_folder": "data/templates",
  "tmp_folder": "data/tmp",
  "trash_auto_delete_days": null,
  "trash_purge_schedule": "0 5 0 * * *",
  "use_sendmail": false,
  "use_syslog": false,
  "user_attachment_limit": null,
  "user_send_limit": null,
  "web_vault_enabled": true,
  "web_vault_folder": "web-vault/",
  "yubico_client_id": null,
  "yubico_secret_key": null,
  "yubico_server": null
}

Vaultwarden Build Version

1.32.3-2f20ad86 (testing tag)

Deployment method

Official Container Image

Custom deployment method

No response

Reverse Proxy

nginx 1.22.1

Host/Server Operating System

Linux

Operating System Version

Debian 12

Clients

Web Vault

Client Version

Firefox 132.0

Steps To Reproduce

Configure SMTP settings with DNS name that both resolves IPv6 and IPv4 address.
As in RFC 6724 it is required that IPv6 is being preferred over IPv4.

Expected Result

Instead of trying to connect to the SMTP host via IPv4 first, it should prefer IPv6. BTW it's a GUA address, no ULA.

Actual Result

The application tries to connect via IPv4 first.

Logs

[2024-11-05 20:53:38.655][request][INFO] POST /admin/test/smtp
[2024-11-05 20:53:39.336][response][INFO] (test_smtp) POST /admin/test/smtp => 200 OK

Screenshots or Videos

No response

Additional Context

No response

Originally created by @imp1sh on GitHub. ### Vaultwarden Support String ### Your environment (Generated via diagnostics page) * Vaultwarden version: v1.32.0-040e2a7b * Web-vault version: v2024.6.2c * OS/Arch: linux/x86_64 * Running within a container: true (Base: Debian) * Environment settings overridden: true * Uses a reverse proxy: true * IP Header check: true (X-Real-IP) * Internet access: true * Internet access via a proxy: false * DNS Check: true * Browser/Server Time Check: false * Server/NTP Time Check: true * Domain Configuration Check: true * HTTPS Check: true * Database type: SQLite * Database version: 3.46.0 * Clients used: * Reverse proxy and version: * Other relevant information: ### Config (Generated via diagnostics page) <details><summary>Show Running Config</summary> **Environment settings which are overridden:** DOMAIN, SIGNUPS_ALLOWED, ADMIN_TOKEN, SMTP_HOST, SMTP_SECURITY, SMTP_PORT, SMTP_FROM, SMTP_USERNAME, SMTP_PASSWORD ```json { "_duo_akey": null, "_enable_duo": false, "_enable_email_2fa": false, "_enable_smtp": true, "_enable_yubico": true, "_icon_service_csp": "", "_icon_service_url": "", "_ip_header_enabled": true, "_max_note_size": 10000, "_smtp_img_src": "cid:", "admin_ratelimit_max_burst": 3, "admin_ratelimit_seconds": 300, "admin_session_lifetime": 20, "admin_token": "***", "allowed_iframe_ancestors": "", "attachments_folder": "data/attachments", "auth_request_purge_schedule": "30 * * * * *", "authenticator_disable_time_drift": false, "data_folder": "data", "database_conn_init": "", "database_max_conns": 10, "database_timeout": 30, "database_url": "***************", "db_connection_retries": 15, "disable_2fa_remember": false, "disable_admin_token": false, "disable_icon_download": false, "domain": "*****://*************", "domain_origin": "*****://*************", "domain_path": "", "domain_set": true, "duo_context_purge_schedule": "30 * * * * *", "duo_host": null, "duo_ikey": null, "duo_skey": null, "duo_use_iframe": false, "email_2fa_auto_fallback": false, "email_2fa_enforce_on_verified_invite": false, "email_attempts_limit": 3, "email_change_allowed": true, "email_expiration_time": 600, "email_token_size": 6, "emergency_access_allowed": true, "emergency_notification_reminder_schedule": "0 3 * * * *", "emergency_request_timeout_schedule": "0 7 * * * *", "enable_db_wal": true, "enable_websocket": true, "enforce_single_org_with_reset_pw_policy": false, "event_cleanup_schedule": "0 10 0 * * *", "events_days_retain": null, "experimental_client_feature_flags": "fido2-vault-credentials", "extended_logging": true, "helo_name": null, "hibp_api_key": null, "http_request_block_non_global_ips": true, "http_request_block_regex": null, "icon_blacklist_non_global_ips": true, "icon_blacklist_regex": null, "icon_cache_folder": "data/icon_cache", "icon_cache_negttl": 259200, "icon_cache_ttl": 2592000, "icon_download_timeout": 10, "icon_redirect_code": 302, "icon_service": "internal", "incomplete_2fa_schedule": "30 * * * * *", "incomplete_2fa_time_limit": 3, "increase_note_size_limit": false, "invitation_expiration_hours": 120, "invitation_org_name": "Vaultwarden", "invitations_allowed": true, "ip_header": "X-Real-IP", "job_poll_interval_ms": 30000, "log_file": null, "log_level": "info", "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f", "login_ratelimit_max_burst": 10, "login_ratelimit_seconds": 60, "org_attachment_limit": null, "org_creation_users": "", "org_events_enabled": false, "org_groups_enabled": false, "password_hints_allowed": true, "password_iterations": 100000, "push_enabled": false, "push_identity_uri": "https://identity.bitwarden.com", "push_installation_id": "***", "push_installation_key": "***", "push_relay_uri": "https://push.bitwarden.com", "reload_templates": false, "require_device_email": false, "rsa_key_filename": "data/rsa_key", "send_purge_schedule": "0 5 * * * *", "sendmail_command": null, "sends_allowed": true, "sends_folder": "data/sends", "show_password_hint": false, "signups_allowed": false, "signups_domains_whitelist": "", "signups_verify": true, "signups_verify_resend_limit": 6, "signups_verify_resend_time": 3600, "smtp_accept_invalid_certs": false, "smtp_accept_invalid_hostnames": false, "smtp_auth_mechanism": null, "smtp_debug": false, "smtp_embed_images": true, "smtp_explicit_tls": null, "smtp_from": "********************", "smtp_from_name": "Vaultwarden - Password Tresor", "smtp_host": "********************", "smtp_password": "***", "smtp_port": 587, "smtp_security": "starttls", "smtp_ssl": true, "smtp_timeout": 15, "smtp_username": "*********************", "templates_folder": "data/templates", "tmp_folder": "data/tmp", "trash_auto_delete_days": null, "trash_purge_schedule": "0 5 0 * * *", "use_sendmail": false, "use_syslog": false, "user_attachment_limit": null, "user_send_limit": null, "web_vault_enabled": true, "web_vault_folder": "web-vault/", "yubico_client_id": null, "yubico_secret_key": null, "yubico_server": null } ``` </details> ### Vaultwarden Build Version 1.32.3-2f20ad86 (testing tag) ### Deployment method Official Container Image ### Custom deployment method _No response_ ### Reverse Proxy nginx 1.22.1 ### Host/Server Operating System Linux ### Operating System Version Debian 12 ### Clients Web Vault ### Client Version Firefox 132.0 ### Steps To Reproduce Configure SMTP settings with DNS name that both resolves IPv6 and IPv4 address. As in RFC 6724 it is required that IPv6 is being preferred over IPv4. ### Expected Result Instead of trying to connect to the SMTP host via IPv4 first, it should prefer IPv6. BTW it's a GUA address, no ULA. ### Actual Result The application tries to connect via IPv4 first. ### Logs ```text [2024-11-05 20:53:38.655][request][INFO] POST /admin/test/smtp [2024-11-05 20:53:39.336][response][INFO] (test_smtp) POST /admin/test/smtp => 200 OK ``` ### Screenshots or Videos _No response_ ### Additional Context _No response_
OVERLORD added the enhancementThird party labels 2025-10-09 16:22:48 +03:00
Author
Owner

@stefan0xC commented on GitHub:

Can you run something like curl ifconfig.me or curl my.ip.fi inside the container to check whether your system prefers IPv6 over IPv4?

@stefan0xC commented on GitHub: Can you run something like `curl ifconfig.me` or `curl my.ip.fi` inside the container to check whether your system prefers IPv6 over IPv4?
Author
Owner

@imp1sh commented on GitHub:

https://github.com/lettre/lettre/issues/1003

@imp1sh commented on GitHub: https://github.com/lettre/lettre/issues/1003
Author
Owner

@BlackDex commented on GitHub:

I think this isn't something specific to Vaultwarden, but more to the mall library/crate https://github.com/lettre/lettre.

It also isn't something we control in Vaultwarden.

@BlackDex commented on GitHub: I think this isn't something specific to Vaultwarden, but more to the mall library/crate https://github.com/lettre/lettre. It also isn't something we control in Vaultwarden.
Author
Owner

@imp1sh commented on GitHub:

Docker sucks with IPv6 tbh
I'm using podman though and my setup is fully tested and functional with IPv6

# curl -6 google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
@imp1sh commented on GitHub: Docker sucks with IPv6 tbh I'm using podman though and my setup is fully tested and functional with IPv6 ``` # curl -6 google.com <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML> ```
Author
Owner

@stefan0xC commented on GitHub:

Do you have IPv6 enabled in docker? Because I don't think that this is the applications fault but should depend on your system setup and I don't think that docker by default can resolve ipv6 addresses.

edit: at least podman cannot do this as far as i've tested it:

root@vaultwarden:/# curl -6 google.at
curl: (7) Failed to connect to google.at port 80 after 30 ms: Couldn't connect to server

(and running my vaultwarden instance locally it seems to connect just fine to the ipv6 address according to the smtp server)

@stefan0xC commented on GitHub: Do you have IPv6 enabled in docker? Because I don't think that this is the applications fault but should depend on your system setup and I don't think that docker by default can resolve ipv6 addresses. edit: at least podman cannot do this as far as i've tested it: ```bash root@vaultwarden:/# curl -6 google.at curl: (7) Failed to connect to google.at port 80 after 30 ms: Couldn't connect to server ``` (and running my vaultwarden instance locally it seems to connect just fine to the ipv6 address according to the smtp server)
Author
Owner

@stefan0xC commented on GitHub:

Well, I'm glad we could narrow it down a bit. So it might be specific to podman and the way it resolves DNS or how you set it up? In any case I don't think I can help any further as I have not enabled IPv6 in podman myself yet and this is probably something you should ask the podman community directly.

@stefan0xC commented on GitHub: Well, I'm glad we could narrow it down a bit. So it might be specific to podman and the way it resolves DNS or how you set it up? In any case I don't think I can help any further as I have not enabled IPv6 in podman myself yet and this is probably something you should ask the [podman community](https://podman.io/community) directly.
Author
Owner

@imp1sh commented on GitHub:

I might have linked the wrong RFC. When it comes to precedence question RFC 6555 is the relevant one.

@imp1sh commented on GitHub: I might have linked the wrong RFC. When it comes to precedence question [RFC 6555](https://datatracker.ietf.org/doc/html/rfc6555) is the relevant one.
Author
Owner

@imp1sh commented on GitHub:

This gives me the IPv4 address when I'm inside a container. But I don't understand... I can both connect to container services inbound via IPv6 and outbound v6 communication basically also works.
Outside of the container it resolves correctly to the IPv6 adress... Weird stuff

@imp1sh commented on GitHub: This gives me the IPv4 address when I'm inside a container. But I don't understand... I can both connect to container services inbound via IPv6 and outbound v6 communication basically also works. Outside of the container it resolves correctly to the IPv6 adress... Weird stuff
Author
Owner

@paolobarbolini commented on GitHub:

On the lettre side we don't do dualstack properly, so it's going to use whichever IP address the resolver returns first.

As for running curl in the container I suggest adding -6 so you are extra sure about it trying to use IPv6. If it doesn't connect you know your container doesn't have an IPv6 address. I don't know much about podman but I know docker only recently released changes that made IPv6 more useful, or at least easier to use, so it could be just that podman has to do the same steps or maybe simply doesn't enable it by default.

@paolobarbolini commented on GitHub: On the lettre side we don't do dualstack properly, so it's going to use whichever IP address the resolver returns first. As for running `curl` in the container I suggest adding `-6` so you are extra sure about it trying to use IPv6. If it doesn't connect you know your container doesn't have an IPv6 address. I don't know much about podman but I know docker only recently released changes that made IPv6 more useful, or at least easier to use, so it could be just that podman has to do the same steps or maybe simply doesn't enable it by default.
Author
Owner

@stefan0xC commented on GitHub:

@paolobarbolini

it's going to use whichever IP address the resolver returns first.

Would that be wrong? I mean that's how the RFC explains how it typically works as well, is it not?

The application would then typically try the first address in the list, looping over the list of addresses until it finds a working address.

@stefan0xC commented on GitHub: @paolobarbolini > it's going to use whichever IP address the resolver returns first. Would that be wrong? I mean that's how [the RFC explains](https://datatracker.ietf.org/doc/html/rfc6724#section-2) how it typically works as well, is it not? > The application would then typically try the first address in the list, looping over the list of addresses until it finds a working address.
Author
Owner

@paolobarbolini commented on GitHub:

Yeah what I meant is that we don't implement happy eyeballs at all

@paolobarbolini commented on GitHub: Yeah what I meant is that we don't implement happy eyeballs at all
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/vaultwarden#328