Just can't get HA Proxy / Vaultwarden to work

I’ve got problems getting HA Proxy configured properly and just can’t find the issue…

My Goal:
Make my self hosted Vaultwarden accessible again via subdomain from WAN and internal networks. e.g.: vault.mydomain.nz
I have the domain registered and DNS management is with Cloudflare pointing to my IP.

Current Situation:
pfSense+ 23.09-RELEASE (amd64)
HA Proxy 0.63_1
acme 0.75

I’m running Vaultwarden (Bitwarden) on a Docker in Proxmox. I made it accessible by using Nginx Proxy Manager for a year now but I had a few occasions where it stopped working because of certificate issues without any reason. I couldn’t fix it this time and decided to ditch NPM and use HAProxy instead.

However, I tried setting up HAProxy on pfSense+ several times from scratch now but I just don’t get it to work. I used these settings: HAproxy inside PfSense and of course tried the 2023 Lawrence setup on YouTube. I also checked another Lawrence video regarding troubleshooting and found 2 possible issues from leftover Nginx PM configuration (NAT and Floating Rule) - which I remedied since but no dice. Also googled a lot and check other posts. When entering the subdomain the browser is loading for a bit but always ends up with a “The connection has timed out”.

I have pfBlockerNG disabled during the setup to make sure no floating rules interfere. Later I will limit port access for 443 and 80 to certain GeoIP regions.

Vaultwarden Docker has different ports mapped on the outside. When I open 192.168.1.30:7011 I get the Vaultwarden GUI, so it’s running.

I changed the pfSense admin ports long time ago.

Either I’m missing something or did something fundamentally wrong? HELP!

Images from my config are crammed into this image (I can only post one)
DNS Resolver for internal access, Firewall Rules, NAT (disabled), ACME Wildcard Cert and HA Backend / Frontend

Not helpful, if you read my post, I already tried that. Either I made a mistake (5 times) or my issue is somewhere else (not the HA Proxy config itself).

Posting config details and what the error message or some error logs (not screenshots of logs) would be more helpful than screenshots. From my troubleshooting I suggest using something like:
openssl s_client -servername google.com -host 142.250.190.78 -port 443
to determine what cert is bring presented.

Hi Tom, thanks for your reply.

I’ve anonymized the domain/IP/cert, this is the output:

openssl s_client -servername mydomain.nz -host 123.123.123.95 -port 443

depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = *.mydomain.nz
verify return:1
CONNECTED(00000003)
---
Certificate chain
 0 s:CN = *.mydomain.nz
   i:C = US, O = Let's Encrypt, CN = R3
   a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA256
   v:NotBefore: Feb  3 20:49:41 2024 GMT; NotAfter: May  3 20:49:40 2024 GMT
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
   v:NotBefore: Jan 20 19:14:03 2021 GMT; NotAfter: Sep 30 18:14:03 2024 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
zj0CAQYFK4EEACIDYgAEBYC040+e/qWDa0GHZqNNMIIELjCCAxagAwIBAgISBPEJ
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
3YyYytTXiUTUcFQwsTpUMA0GCSqGSIb3DQEBCwUACCouNDA0Lm56MHYwEAYHKoZI
2oC3NW8aNfW+wrkZQoE/CH579+ThTCZCm7txPlKtRfd5cq45frcn+g95zxjJBHmU
mZBwyjIcWexCiQCbtSwmOddDB1hZKHnBg/K7SaC7uWcPo4ICCTCCAgUwDgYDVR0P
AQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB
Af8EAjAAMB0GA1UdDgQWBBS4lJPQqszVpGI2r6VV/pO7cmIkFTAfBgNVHSMEGDAW
gBQULrMXt1hWy65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUH
EwJSMzAeFw0yNDAyMDMyMDQ5NDFaFw0yNDA1MDMyMDQ5NDBaMBMxETAPBgNVBAMM
MAGGFWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3Iz
LmkubGVuY3Iub3JnLzATBgNVHREEDDAKgggqLjQwNC5uejATBgNVHSAEDDAKMAgG
BmeBDAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AKLiv9Ye3i8vB6DWTm03
p9xlQ7DGtS6i2reK+Jpt9RfYAAABjXDy3vcAAAQDAEYwRAIgZUlvVH4l1d+loY1k
XnUUK7FwYcqXaAJOvd6QUaUvTLoCIEk8KdA2fKYBRI89UUkOK/pLqQkgnbgaIiPo
aOZvFHekAHYAdv+IPwq2+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGNcPLf
tAAABAMARzBFAiBZtmOEtKe98TY2hzgw6r08wErpz8SMnZzLeBug+d2G3wIhAMl6
UIw484UPWsz5GVP1P5x8X1Rls238wsj9ysMlcCh9KtAg7u7V2+IQmmMJybLE7S2L
BmeBDAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AKLiv9Ye3i8vB6DWTm03
AQBw+3QErwbTMSMcJXASkzQespQs1Y78Zv/JCd5UXpREkb2etxhRthQTJMxZy4vc
h7OW9b74M+w99FYjmvK7JPuLLWt6OgYIAxbHhQjrqla5GiDCyq7l3dqPQqYF0lm3
Pzovme1NBKpLMi01Ndg5wB5xxmuAyrcRQyLv58+qbx0G+2O8lE3fPj0SqgnNMBDd
z5feDzS49+jgT7BS75OVOtoGa4TWSMP35ko8FLxQNyTd8s+IxRyIEuM+P/zZl1SW
+Vx9l03t7YS+99EYzj0mM28AEG/ZXsQzHroKw9IgMrV+S+f/clv8TWvLz/A0QREV
MA0GCSqGSIb3DQEBCwUAA4IB
-----END CERTIFICATE-----
subject=CN = *.mydomain.nz
issuer=C = US, O = Let's Encrypt, CN = R3
---
No client certificate CA names sent
Peer signing digest: SHA384
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4160 bytes and written 382 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 384 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
DONE

I’ll post the HA Proxy config shortly or is there another particular one that would be helpful?
Regarding logfiles… it’s probably more a question what to look for. HA Proxy messages in the System log?

Regards

Excerpt config from pfSense: (some values changed for privacy)

<installedpackages>
	<package>
		<name>acme</name>
		<pkginfolink>https://docs.netgate.com/pfsense/en/latest/packages/acme/index.html</pkginfolink>
		<descr><![CDATA[Automated Certificate Management Environment, for automated use of LetsEncrypt certificates.]]></descr>
		<website>https://letsencrypt.org/</website>
		<version>0.7.5</version>
		<configurationfile>acme.xml</configurationfile>
		<include_file>/usr/local/pkg/acme/acme.inc</include_file>
		<plugins>
			<item>
				<type>plugin_certificates</type>
			</item>
		</plugins>
	</package>
	<package>
		<name>haproxy</name>
		<pkginfolink>https://docs.netgate.com/pfsense/en/latest/packages/haproxy.html</pkginfolink>
		<descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer.&lt;br /&gt;
			This package implements the TCP, HTTP and HTTPS balancing features from haproxy.&lt;br /&gt;
			Supports ACLs for smart backend switching.]]></descr>
		<website>http://haproxy.1wt.eu/</website>
		<version>0.63_1</version>
		<configurationfile>haproxy.xml</configurationfile>
		<logging>
			<logsocket>/tmp/haproxy_chroot/var/run/log</logsocket>
			<facilityname>haproxy</facilityname>
			<logfilename>haproxy.log</logfilename>
		</logging>
		<filter_rule_function>haproxy_generate_rules</filter_rule_function>
		<include_file>/usr/local/pkg/haproxy/haproxy.inc</include_file>
		<plugins>
			<item>
				<type>plugin_carp</type>
			</item>
			<item>
				<type>plugin_certificates</type>
			</item>
		</plugins>
	</package>
	
	
	<haproxy>
		<ha_backends>
			<item>
				<name>Subdomains404nz</name>
				<descr><![CDATA[*.mydomain.nz]]></descr>
				<status>active</status>
				<type>http</type>
				<httpclose>http-keep-alive</httpclose>
				<ssloffloadcert>65beb4eec8e44</ssloffloadcert>
				<ssloffloadacl_an>yes</ssloffloadacl_an>
				<advanced></advanced>
				<ha_acls>
					<item>
						<name>vault</name>
						<expression>host_matches</expression>
						<value>vault.mydomain.nz</value>
						<backendservercountbackend>Vaultwarden</backendservercountbackend>
						<_index></_index>
					</item>
				</ha_acls>
				<ha_certificates></ha_certificates>
				<clientcert_ca></clientcert_ca>
				<clientcert_crl></clientcert_crl>
				<a_extaddr>
					<item>
						<extaddr>wan_ipv4</extaddr>
						<extaddr_port>443</extaddr_port>
						<extaddr_ssl>yes</extaddr_ssl>
						<_index></_index>
					</item>
				</a_extaddr>
				<a_actionitems>
					<item>
						<action>use_backend</action>
						<acl>vault</acl>
						<use_backendbackend>Vaultwarden</use_backendbackend>
						<_index></_index>
					</item>
				</a_actionitems>
				<a_errorfiles></a_errorfiles>
				<forwardfor>yes</forwardfor>
				<ssloffloadacl>yes</ssloffloadacl>
			</item>
		</ha_backends>
		<ha_pools>
			<item>
				<ha_servers>
					<item>
						<status>active</status>
						<name>Vaultwarden</name>
						<address>192.168.1.30</address>
						<port>7011</port>
						<id>101</id>
						<_index></_index>
					</item>
				</ha_servers>
				<a_acl></a_acl>
				<a_actionitems></a_actionitems>
				<errorfiles></errorfiles>
				<advanced></advanced>
				<advanced_backend></advanced_backend>
				<name>Vaultwarden</name>
				<balance></balance>
				<balance_urilen></balance_urilen>
				<balance_uridepth></balance_uridepth>
				<balance_uriwhole></balance_uriwhole>
				<transparent_clientip></transparent_clientip>
				<transparent_interface>lan</transparent_interface>
				<check_type>none</check_type>
				<checkinter></checkinter>
				<log-health-checks></log-health-checks>
				<httpcheck_method>OPTIONS</httpcheck_method>
				<monitor_uri></monitor_uri>
				<monitor_httpversion></monitor_httpversion>
				<monitor_username></monitor_username>
				<monitor_domain></monitor_domain>
				<monitor_agentport>Vaultwarden</monitor_agentport>
				<agent_check></agent_check>
				<agent_port></agent_port>
				<agent_inter></agent_inter>
				<connection_timeout></connection_timeout>
				<server_timeout></server_timeout>
				<retries></retries>
				<stats_enabled></stats_enabled>
				<stats_username></stats_username>
				<stats_password></stats_password>
				<stats_uri></stats_uri>
				<stats_scope></stats_scope>
				<stats_realm></stats_realm>
				<stats_admin></stats_admin>
				<stats_node></stats_node>
				<stats_desc></stats_desc>
				<stats_refresh></stats_refresh>
				<persist_stick_expire></persist_stick_expire>
				<persist_stick_tablesize></persist_stick_tablesize>
				<persist_stick_length></persist_stick_length>
				<persist_stick_cookiename></persist_stick_cookiename>
				<persist_sticky_type>none</persist_sticky_type>
				<persist_cookie_enabled></persist_cookie_enabled>
				<persist_cookie_name></persist_cookie_name>
				<persist_cookie_mode>passive</persist_cookie_mode>
				<persist_cookie_cachable></persist_cookie_cachable>
				<persist_cookie_postonly></persist_cookie_postonly>
				<persist_cookie_httponly></persist_cookie_httponly>
				<persist_cookie_secure></persist_cookie_secure>
				<haproxy_cookie_maxidle></haproxy_cookie_maxidle>
				<haproxy_cookie_maxlife></haproxy_cookie_maxlife>
				<haproxy_cookie_domains></haproxy_cookie_domains>
				<haproxy_cookie_dynamic_cookie_key></haproxy_cookie_dynamic_cookie_key>
				<strict_transport_security></strict_transport_security>
				<cookie_attribute_secure></cookie_attribute_secure>
				<email_level></email_level>
				<email_to></email_to>
				<id>100</id>
			</item>
		</ha_pools>

		<configversion>00.58</configversion>
		<files></files>
		<email_mailers></email_mailers>
		<dns_resolvers></dns_resolvers>
		<maxconn>100</maxconn>
		<logfacility>local0</logfacility>
		<loglevel>info</loglevel>
		<localstatsport>2200</localstatsport>
		<nbthread></nbthread>
		<hard_stop_after></hard_stop_after>
		<localstats_refreshtime></localstats_refreshtime>
		<localstats_sticktable_refreshtime></localstats_sticktable_refreshtime>
		<log-send-hostname></log-send-hostname>
		<ssldefaultdhparam>2048</ssldefaultdhparam>
		<email_level></email_level>
		<email_myhostname></email_myhostname>
		<email_from></email_from>
		<email_to></email_to>
		<resolver_retries></resolver_retries>
		<resolver_timeoutretry></resolver_timeoutretry>
		<resolver_holdvalid></resolver_holdvalid>
		<enable></enable>
		<terminate_on_reload></terminate_on_reload>
		<sslcompatibilitymode>intermediate</sslcompatibilitymode>
	</haproxy>
	
	<acme>
		<accountkeys>
			<item>
				<accountkey>*** REMOVED FOR PRIVACY ***</accountkey>
				<name>mydomain.nz</name>
				<descr><![CDATA[For Vaultwarden]]></descr>
				<email><![CDATA[myemail@mydomain.nz]]></email>
				<acmeserver>letsencrypt-production-2</acmeserver>
				<renewafter></renewafter>
			</item>
		</accountkeys>
		<certificates>
			<item>
				<a_domainlist>
					<item>
						<status>enable</status>
						<name>*.mydomain.nz</name>
						<method>dns_cf</method>
						<dns_nsupdatensupdate_keyalgo>157</dns_nsupdatensupdate_keyalgo>
						<dns_cfcf_token>123123PVXpLr1234565JuZsfLxgbi8L3MB4722fa</dns_cfcf_token>
						<dns_cfcf_account_id>123123cc1234565d7b7fa8b7089eee31</dns_cfcf_account_id>
						<dns_cfcf_zone_id>1231239096754e200a12345647533eac</dns_cfcf_zone_id>
						<_index></_index>
					</item>
				</a_domainlist>
				<a_actionlist>
					<item>
						<status>enable</status>
						<command>/usr/local/etc/rc.d/haproxy.sh restart</command>
						<method>shellcommand</method>
						<_index></_index>
					</item>
				</a_actionlist>
				<keypaste></keypaste>
				<name>Wildcardmydomain.nz</name>
				<descr><![CDATA[*.mydomain.nz (Wildcard)]]></descr>
				<status>active</status>
				<acmeaccount>mydomain.nz</acmeaccount>
				<keylength>ec-384</keylength>
				<ocspstaple></ocspstaple>
				<preferredchain></preferredchain>
				<dnssleep></dnssleep>
				<renewafter></renewafter>
				<lastrenewal>1706996983</lastrenewal>
			</item>
		</certificates>
		<enable>yes</enable>
		<writecerts></writecerts>
	</acme>
</installedpackages>

With the openssl command are you asking for vault.mydomain.nz or mydomain.nz as you show in the command? What is the DNS entry for vault.mydomain.nz?

Right, I used mydomain.nz which is incorrect since that is hosted somewhere else with a different cert.

Executing the openssl command for vault.mydomain.nz indeed fails with a timeout:

0020C17DF63D0000:error:8000003C:system library:BIO_connect:Operation timed out:/var/jenkins/workspace/pfSense-Plus-snapshots-23_09-main/sources/FreeBSD-src-plus-RELENG_23_09/crypto/openssl/crypto/bio/bio_sock2.c:125:calling connect()
0020C17DF63D0000:error:10000067:BIO routines:BIO_connect:connect error:/var/jenkins/workspace/pfSense-Plus-snapshots-23_09-main/sources/FreeBSD-src-plus-RELENG_23_09/crypto/openssl/crypto/bio/bio_sock2.c:127:
connect:errno=60

Makes me wonder though why ACME reports a seemingly successful certificate retrieval.

At first glance I would drop the DNS Host Override, as anything locally trying to hit that host will simply bypass your proxy - it’s just hitting the host directly.

I disabled it but it doesn’t seem to change anything. I requested a new cert which seem to have worked fine and when running the openssl command to check I get the response below which looks ok? (altered for privacy)

I just don’t know where to look for the issue or what it can be. Going through endless logfiles doesn’t seem to be productive either if you don’t know what to look for and in which logfile.

Any other ideas? Otherwise I’m about to give up on HAProxy I think…

root@SERVER:~# openssl s_client -servername vault.mydomain.nz -host 152.223.227.15 -port 443
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = *.mydomain.nz
verify return:1
---
Certificate chain
 0 s:CN = *.mydomain.nz
   i:C = US, O = Let's Encrypt, CN = R3
   a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA256
   v:NotBefore: Feb 14 16:53:04 2024 GMT; NotAfter: May 14 16:53:03 2024 GMT
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
   v:NotBefore: Jan 20 19:14:03 2021 GMT; NotAfter: Sep 30 18:14:03 2024 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
2oC3NW8aNfW+wrIBAgISAz4sW2+GXZ5SBrZuoTcsBmlaMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yNDAyMTQxNjUzMDRaFw0yNDA1MTQxNjUzMDNaMBMxETAPBgNVBAMM
CCouNDA0Lm56MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBYC040+e/qWDa0GHZqNN
2oC3NW8aNfW+wrkZQoE/CH579+ThTCZCm7txPlKtRfd5cq45frcn+g95zxjJBHmU
mZBwyjIcWexCiQCbtSwmOddDB1hZKHnBg/K7SaC7uWcPo4ICDDCCAggwDgYDVR0P
AQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB
Af8EAjAAMB0GA1UdDgQWBBS4lJPQqszVpGI2r6VV/pO7cmIkFTAfBgNVHSMEGDAW
CCouNDA0Lm56MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBYC040+e/qWDa0GHZqNN
MAGGFWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3Iz
CCouNDA0Lm56MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBYC040+e/qWDa0GHZqNN
BmeBDAECATCCAQYGCisGAQQB1nkCBAIEgfcEgfQA8gB3AHb/iD8KtvuVUcJhzPWH
ujS0pM27KdxoQgqf5mdMWjp0AAABjajAMWUAAAQDAEgwRgIhANf4m1ROgEfeyR7N
uqJkgF6CHx9HVyi5bsIk4XvDM4r6AiEApPhJCoTbrmFXH//UcEmLXQcx02rTRcAw
IZRfLNIPdUYAdwCi4r/WHt4vLweg1k5tN6fcZUOwxrUuotq3iviabfUX2AAAAY2o
uqJkgF6CHx9HVyi5bsIk4XvDM4r6AiEApPhJCoTbrmFXH//UcEmLXQcx02rTRcAw
AKQmkANgao2Xn1yUeNcabs1palijhmMjQ86AHGzFm1IgMA0GCSqGSIb3DQEBCwUA
uqJkgF6CHx9HVyi5bsIk4XvDM4r6AiEApPhJCoTbrmFXH//UcEmLXQcx02rTRcAw
Z+gWm/k09HDRo9DzaMwn8eHMi5nBDx1V6pZlKh3gjXOkUV0Hq+sOB4irYy9VCghb
0hq8rYVHINubl27taCRO4n3YCQPXFm4SbECPPEhPDVx/sRj+uji5teUFrMY+EaLd
PFhSx4qcogsux5RW/2e4WiGp2QI4t8eyKjdroV187mXb2zw9RiNfqFmQ0fGI+gQ/
PFhSx4qcogsux5RW/2e4WiGp2QI4t8eyKjdroV187mXb2zw9RiNfqFmQ0fGI+gQ/
m1IgMA0GCSqGSIb3DQEBCwUAgqmw
-----END CERTIFICATE-----
subject=CN = *.mydomain.nz
issuer=C = US, O = Let's Encrypt, CN = R3
---
No client certificate CA names sent
Peer signing digest: SHA384
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4164 bytes and written 382 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 384 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_128_GCM_SHA256
    Session-ID: E8F3D0AE3FB3C53C97D7B5BA3E7BEF6278463E6FC6233558CA964A195D350079
    Session-ID-ctx: 
    Resumption PSK: D74343376C7B041BD037F142A715FE2D86E803B54A3B045D2DC7981500098850
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 79 a8 6b e9 31 5d 65 2a-02 d3 fe e8 af b1 ce 51   y.k.1]e*.......Q
    0010 - 3b fd c3 70 fa a9 3c 82-74 36 a8 c4 4e 57 9a 45   ;..p..<.t6..NW.E

    Start Time: 1707985054
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_128_GCM_SHA256
    Session-ID: 3A041A599E4B1DCA6498F92158784A5811594F8F982123A435D1DC7F1DC53D33
    Session-ID-ctx: 
    Resumption PSK: 5FEFEE32A2F03FB856EE634379C3D95A78DCCA78FF8D081C863B716E5BD97B47
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 41 ec e5 cb 70 50 00 65-53 c5 20 c4 4f 8e 57 d9   A...pP.eS. .O.W.
    0010 - 0d 74 0c 9b 31 40 e0 00-71 f1 36 8e 7b fa 4d 67   .t..1@..q.6.{.Mg

    Start Time: 1707985054
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
HTTP/1.1 408 Request Time-out
Content-length: 110
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>
closed

Sorry we haven’t been able to help here, without a more detailed look into your specific config and because of all the (necessary) obfuscation, It’s tricky to know what to suggest. But here’s a couple things I would look into:

  • Confirm public and private DNS for vault.mydomain.nz resolves to your public WAN IP.
    • Things get a little more complicated if you’re behind a dynamic IP, but still doable.
    • You’ve shown certs are renewing, but because it’s a wildcard cert and I’m assuming you’re using Let’s Encrypt certs with ACME on pfSense, you’re likely having to manually update a _acme-challenge.mydomain.nz TXT record. All this to say that while the wildcard certificate for *.mydomain.nz might be fine, you still need vault.mydomain.nz to resolve properly. Also note that wildcards don’t apply to sub-domains, such that vault.sub1.mydomain.nz would need another *.sub1.mydomain.nz cert.
  • Confirm via HAProxy Stats whether the backend is online and in a READY state.
    • You can configure Health Checking for a VaultWarden backend with an HTTP GET method to the /alive URL.
  • Confirm the HAProxy Frontend is configured properly, and not being intercepted by another Frontend.
    • Interface Address, Port, ACL, Backend & SSL Offloading all critical here.
  • Also not necessarily applicable here, but remember to restart the HAProxy Service after you’ve renewed/reissued any certificates in use by it.

Hi, thanks for taking the time to reply…

Today I discovered something which I thought might have been the issue. While it definitely was a breaking issue, it probably only was another non working piece.

So, I do have a dynamic DNS and pfSense is updating that at Cloudflare … or so I thought. It actually did for a while but for security reasons I replaced the global Cloudflare API key with a custom API key which is restricted to DNS changes for a specific zone only. However, that doesn’t seem to work properly, at least not with pfSense and the updates failed. I now swapped back to the global key and the updates work again and then I flushed all my DNS caches.
As a sidenote, on another system somewhere else I use the custom key in a script and it does work fine.

Regarding Let’s Encrypt certs and TXT record, I don’t think a TXT record is required since I use the Cloudflare API for that.

Here is a screenshot of the HAProxy STATS page.

I only have 1 Frontend defined currently. I only use 1 level subdomains like vault.domain.nz
Current HA Proxy config:

<haproxy>
		<ha_backends>
			<item>
				<name>vault</name>
				<descr><![CDATA[vault.mydomain.nz]]></descr>
				<status>active</status>
				<type>http</type>
				<httpclose>http-keep-alive</httpclose>
				<ssloffloadcert>65beb4eec8e44</ssloffloadcert>
				<ssloffloadacl_an>yes</ssloffloadacl_an>
				<advanced></advanced>
				<ha_acls>
					<item>
						<name>vault</name>
						<expression>host_matches</expression>
						<value>vault.mydomain.nz</value>
						<backendservercountbackend>Vaultwarden</backendservercountbackend>
						<_index></_index>
					</item>
				</ha_acls>
				<ha_certificates></ha_certificates>
				<clientcert_ca></clientcert_ca>
				<clientcert_crl></clientcert_crl>
				<a_extaddr>
					<item>
						<extaddr>wan_ipv4</extaddr>
						<extaddr_port>443</extaddr_port>
						<extaddr_ssl>yes</extaddr_ssl>
						<_index></_index>
					</item>
				</a_extaddr>
				<a_actionitems>
					<item>
						<action>use_backend</action>
						<acl>vault</acl>
						<use_backendbackend>Vaultwarden</use_backendbackend>
						<_index></_index>
					</item>
				</a_actionitems>
				<a_errorfiles></a_errorfiles>
			</item>
		</ha_backends>
		
		<ha_pools>
			<item>
				<ha_servers>
					<item>
						<status>active</status>
						<name>Vaultwarden</name>
						<address>192.168.1.30</address>
						<port>7011</port>
						<id>101</id>
						<_index></_index>
					</item>
				</ha_servers>
				<a_acl></a_acl>
				<a_actionitems></a_actionitems>
				<errorfiles></errorfiles>
				<advanced></advanced>
				<advanced_backend></advanced_backend>
				<name>Vaultwarden</name>
				<balance></balance>
				<balance_urilen></balance_urilen>
				<balance_uridepth></balance_uridepth>
				<balance_uriwhole></balance_uriwhole>
				<transparent_clientip></transparent_clientip>
				<transparent_interface>lan</transparent_interface>
				<check_type>Basic</check_type>
				<checkinter></checkinter>
				<log-health-checks></log-health-checks>
				<httpcheck_method>OPTIONS</httpcheck_method>
				<monitor_uri></monitor_uri>
				<monitor_httpversion></monitor_httpversion>
				<monitor_username></monitor_username>
				<monitor_domain></monitor_domain>
				<monitor_agentport>Vaultwarden</monitor_agentport>
				<agent_check></agent_check>
				<agent_port></agent_port>
				<agent_inter></agent_inter>
				<connection_timeout></connection_timeout>
				<server_timeout></server_timeout>
				<retries></retries>
				<stats_enabled></stats_enabled>
				<stats_username></stats_username>
				<stats_password></stats_password>
				<stats_uri></stats_uri>
				<stats_scope></stats_scope>
				<stats_realm></stats_realm>
				<stats_admin></stats_admin>
				<stats_node></stats_node>
				<stats_desc></stats_desc>
				<stats_refresh></stats_refresh>
				<persist_stick_expire></persist_stick_expire>
				<persist_stick_tablesize></persist_stick_tablesize>
				<persist_stick_length></persist_stick_length>
				<persist_stick_cookiename></persist_stick_cookiename>
				<persist_sticky_type>none</persist_sticky_type>
				<persist_cookie_enabled></persist_cookie_enabled>
				<persist_cookie_name></persist_cookie_name>
				<persist_cookie_mode>passive</persist_cookie_mode>
				<persist_cookie_cachable></persist_cookie_cachable>
				<persist_cookie_postonly></persist_cookie_postonly>
				<persist_cookie_httponly></persist_cookie_httponly>
				<persist_cookie_secure></persist_cookie_secure>
				<haproxy_cookie_maxidle></haproxy_cookie_maxidle>
				<haproxy_cookie_maxlife></haproxy_cookie_maxlife>
				<haproxy_cookie_domains></haproxy_cookie_domains>
				<haproxy_cookie_dynamic_cookie_key></haproxy_cookie_dynamic_cookie_key>
				<strict_transport_security></strict_transport_security>
				<cookie_attribute_secure></cookie_attribute_secure>
				<email_level></email_level>
				<email_to></email_to>
				<id>100</id>
			</item>
		</ha_pools>
		<configversion>00.58</configversion>
		<files></files>
		<email_mailers></email_mailers>
		<dns_resolvers></dns_resolvers>
		<maxconn>100</maxconn>
		<logfacility>local0</logfacility>
		<loglevel>debug</loglevel>
		<localstatsport>2200</localstatsport>
		<nbthread></nbthread>
		<hard_stop_after></hard_stop_after>
		<localstats_refreshtime></localstats_refreshtime>
		<localstats_sticktable_refreshtime></localstats_sticktable_refreshtime>
		<log-send-hostname></log-send-hostname>
		<ssldefaultdhparam>2048</ssldefaultdhparam>
		<email_level></email_level>
		<email_myhostname></email_myhostname>
		<email_from></email_from>
		<email_to></email_to>
		<resolver_retries></resolver_retries>
		<resolver_timeoutretry></resolver_timeoutretry>
		<resolver_holdvalid></resolver_holdvalid>
		<terminate_on_reload></terminate_on_reload>
		<sslcompatibilitymode>intermediate</sslcompatibilitymode>
		<enable></enable>
	</haproxy>

A remote Linux system returns correct IP when doing a dig or ping on vault.mydomain.nz.
When I try openssl s_client -servername vault.mydomain.nz -host 123.123.123.95 -port 443 I get a timeout though.

A local Linux can ping vault.mydomain.nz which resolves to pfSense’s IP address (192.168.1.2) as defined in the DNS resolver. (that same IP is also the Linux’ only DNS server in resolv.conf).
Running openssl s_client -servername vault.mydomain.nz -host 123.123.123.95 -port 443 on the local Linux does return a certificate.

That seems like pfSense/HAProxy is not serving or answering requests from WAN which makes me wonder if something is wrong with my firewall rules but my WAN rules are pretty simple:

<rule>
		<id></id>
		<tracker>1708120689</tracker>
		<type>pass</type>
		<interface>wan</interface>
		<ipprotocol>inet</ipprotocol>
		<tag></tag>
		<tagged></tagged>
		<max></max>
		<max-src-nodes></max-src-nodes>
		<max-src-conn></max-src-conn>
		<max-src-states></max-src-states>
		<statetimeout></statetimeout>
		<statetype><![CDATA[keep state]]></statetype>
		<os></os>
		<protocol>tcp</protocol>
		<srcmac></srcmac>
		<dstmac></dstmac>
		<source>
			<network>wanip</network>
		</source>
		<destination>
			<network>(self)</network>
			<port>80</port>
		</destination>
		<descr><![CDATA[HAProxy HTTP]]></descr>
		<bridgeto></bridgeto>
		<updated>
			<time>1708120689</time>
			<username><![CDATA[admin@172.16.16.8 (Local Database)]]></username>
		</updated>
		<created>
			<time>1708120689</time>
			<username><![CDATA[admin@172.16.16.8 (Local Database)]]></username>
		</created>
	</rule>
	<rule>
		<id></id>
		<tracker>1708120727</tracker>
		<type>pass</type>
		<interface>wan</interface>
		<ipprotocol>inet</ipprotocol>
		<tag></tag>
		<tagged></tagged>
		<max></max>
		<max-src-nodes></max-src-nodes>
		<max-src-conn></max-src-conn>
		<max-src-states></max-src-states>
		<statetimeout></statetimeout>
		<statetype><![CDATA[keep state]]></statetype>
		<os></os>
		<protocol>tcp</protocol>
		<srcmac></srcmac>
		<dstmac></dstmac>
		<source>
			<network>wanip</network>
		</source>
		<destination>
			<network>(self)</network>
			<port>443</port>
		</destination>
		<descr><![CDATA[HAProxy HTTPS]]></descr>
		<bridgeto></bridgeto>
		<updated>
			<time>1708120727</time>
			<username><![CDATA[admin@172.16.16.8 (Local Database)]]></username>
		</updated>
		<created>
			<time>1708120727</time>
			<username><![CDATA[admin@172.16.16.8 (Local Database)]]></username>
		</created>
	</rule>

Only have 1 floating rule which only affects another interface.
Does this give away any clues?

CHeers

You’re close, but the issue is still your local DNS override for vault.mydomain.nz, which currently seems to be your pfSense LAN IP.

  • Either get rid of the override, so it resolves to the public WAN IP.
  • Or add your pfSense LAN IP:443 to the HAProxy Frontend.

Yes sorry, if you’re using Cloudflare API, scratch the manual TXT record stuff I said.

For convenience, you can add a shell command action to the Acme Cert to restart HA Proxy on renewals: /usr/local/etc/rc.d/haproxy.sh restart

Oh and, I can’t recall, but have you moved the default port pfSense runs on away from 443 under System > Advanced > Admin Access > webConfigurator > TCP port?

I got rid of the override but that would only have affected request from inside my network or not? I’m fine if it resolves to the WAN address.

Thanks for the shell command but I already had that in, I believe that was in the Lawrence video as well.

My default pfSense port is 10443.

However, it’s still not working.It still ends up in a timeout. I’ve no ideas where/when things get stuck. At the firewall, at HA Proxy, somewhere else?