SSL Cert for subdomains natted to a different port


I’m very new when is comes to Letsencrypt and SSL Certs in general and not sure if what i want to do is possible. I have a server behind a pfSense firewall that serves multiple applications on different ports. All of the web apps are accessible using nat through pfSense to route to url:port to the correct app. I have setup a domain name with Google Domains and added subdomain redirects to the various url:ports. All of this works fine.

I would like to add a wildcard cert inside pfSense that covers all of the domains. It seems to work for the top level domain fine, but all subdomains show an error and won’t let me connect with the Net::err_cert_authority_invalid message and something about hsts.

My question is , is what i am trying to do possible? I am also using the pfsense Acme package to add and configure the cert and using manual dns challenge with the txt file. Thanks so much!


Have you added the wildcard certificate to be served from the actual server that the traffic is being directed to?


no i have not. i didn’t know that was a step i needed to take since pfsense is hosting the cert. The server machine is a ubuntu desktop 16.04 vm. Do you know of a link that would explain how to do this. I’ve searched but cant find anything directly related? Sounds like i need to export the cert and key from pfsense and import into ubuntu right?


What web service application are you using?

Apache? Nginx? etc

Usually it’ll be specific to that server software but yeah you’ll have to place the key/cert on the server and then call it from that applications configuration file to be served for each visit.


Yes it’s Apache. i exported the crt and key file from pfsense, edited the default-ssl.conf in ubuntu and changed the Virtualhost *:443 paths to the new cert files but still got the same error when trying to browse to those applications.


Well, that depends on what protocol level the proxying is taking place at. Is pfSense proxying at the TCP level or at the HTTPS level here?


I do not know the answer to that right away. Google domains is forwarding subdomains to the domainname:port, pfsense receives the port and nats to the correct local server. does that answer your question? if not how do i determine what level the proxy is occuring?


I wonder if maybe you enabled HSTS (a Strict-Transport-Security header) with the includeSubDomains directive?

That would mean your browser is forced to try to access the subdomains over HTTPS before they get a chance to redirect to the correct port on your pfsense server. If Google Domains is performing the redirects, then it needs a valid certificate to handle them because it will receive those initial requests over HTTPS because of HSTS.

(though I haven’t used Google Domains so I may be talking through my hat)


Could you tell us the actual domain names here?


Here are the google domain settings with the subdomain redirects. The domain is


I think there are several different things going on here that create different problems. We can certainly delve into all of them, but I’d like to start by saying that I’m skeptical of the strategy of using the Google Domains forwarding here.

(1) It means that you can never use HTTPS on any of these subdomains and that if anyone tries to, it won’t work.
(2) It means that the HSTS settings that are already in place will cause things to break.
(3) The “Do not forward path” means that none of these domains can be used with direct links to anything but the top-level homepage.

Effectively, this kind of forwarding is functioning something like a bookmark to a site’s homepage, except that the bookmark is maintained by Google Domains rather than in individual users’ browsers.

Would you be willing to consider changing this so that the subdomains all point directly to your server via a CNAME record rather than via HTTP subdomain forwards? Then you would change how pfSense handles the proxying.


Yes, i would absolutely be willing to change things around. I’ll start adding the cnames records now. Does it matter that I am using ddns through google domains since I have a dynamic IP? Do i add the port in the domain field for the cname record? Not sure how i would route in pfsense though if it’s not coming from a specific port.


I guess the next question is how do i import the certificate into the ubuntu machine so that it works properly. I’ve found a few different ways but not sure the correct approach for my stuation.


I expect that pfSense or some other proxy is going to need to receive all of the connections on port 443, and it’s going to need to have certificates for all of the names, or simply one certificate that covers all of them. Then, it will need to proxy the connections to the appropriate ports or servers.


pfsense already has the correct certificates. it’s a wildcard certificate that covers the subdomains. It is working on the top level domain properly. If I browse to the subdomain with the port, it connects but says unsecured. and when i check the cert info, it says its using a ubuntu cert. I dont know what to do to make the vm server serve the cert.


Sure, though one option would be to use port 443 for everything and have the proxy handle the proxying to a different port. You don’t necessarily have to continue to use port forwarding, at least not port forwarding visible to the end-user of the site.

For the approach that you were planning on, what kind of web server software are the VMs using?


when you say proxy, you are referring to pfsense right? The Ubuntu vm is running Apache. Is that what you’re asking? Sorry for being a little dense.



So, could you post your Apache configuration here?



This is the main Apache server configuration file. It contains the

configuration directives that give the server its instructions.

See for detailed information about

the directives and /usr/share/doc/apache2/README.Debian about Debian specific


Summary of how the Apache 2 configuration works in Debian:

The Apache 2 web server configuration in Debian is quite different to

upstream’s suggested way to configure the web server. This is because Debian’s

default Apache2 installation attempts to make adding and removing modules,

virtual hosts, and extra configuration directives as flexible as possible, in

order to make automating the changes and administering the server as easy as


It is split into several files forming the configuration hierarchy outlined

below, all located in the /etc/apache2/ directory:


|-- apache2.conf

| `-- ports.conf

|-- mods-enabled

| |-- *.load

| `-- *.conf

|-- conf-enabled

| `-- *.conf

`-- sites-enabled

`-- *.conf

* apache2.conf is the main configuration file (this file). It puts the pieces

together by including all remaining configuration files when starting up the

web server.

* ports.conf is always included from the main configuration file. It is

supposed to determine listening ports for incoming connections which can be

customized anytime.

* Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/

directories contain particular configuration snippets which manage modules,

global configuration fragments, or virtual host configurations,


They are activated by symlinking available configuration files from their

respective *-available/ counterparts. These should be managed by using our

helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See

their respective man pages for detailed information.

* The binary is called apache2. Due to the use of environment variables, in

the default configuration, apache2 needs to be started/stopped with

/etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not

work with the default configuration.

Global configuration

ServerRoot: The top of the directory tree under which the server’s

configuration, error, and log files are kept.

NOTE! If you intend to place this on an NFS (or otherwise network)

mounted filesystem then please read the Mutex documentation (available

at URL:;

you will save yourself a lot of trouble.

Do NOT add a slash at the end of the directory path.

#ServerRoot “/etc/apache2”

The accept serialization lock file MUST BE STORED ON A LOCAL DISK.

Mutex file:${APACHE_LOCK_DIR} default

PidFile: The file in which the server should record its process

identification number when it starts.

This needs to be set in /etc/apache2/envvars


Timeout: The number of seconds before receives and sends time out.

Timeout 300

KeepAlive: Whether or not to allow persistent connections (more than

one request per connection). Set to “Off” to deactivate.

KeepAlive On

MaxKeepAliveRequests: The maximum number of requests to allow

during a persistent connection. Set to 0 to allow an unlimited amount.

We recommend you leave this number high, for maximum performance.

MaxKeepAliveRequests 100

KeepAliveTimeout: Number of seconds to wait for the next request from the

same client on the same connection.

KeepAliveTimeout 5

These need to be set in /etc/apache2/envvars


HostnameLookups: Log the names of clients or just their IP addresses

e.g., (on) or (off).

The default is off because it’d be overall better for the net if people

had to knowingly turn this feature on, since enabling it means that

each client request will result in AT LEAST one lookup request to the


HostnameLookups Off

ErrorLog: The location of the error log file.

If you do not specify an ErrorLog directive within a

container, error messages relating to that virtual host will be

logged here. If you do define an error logfile for a

container, that host’s errors will be logged there and not here.

ErrorLog ${APACHE_LOG_DIR}/error.log

LogLevel: Control the severity of messages logged to the error_log.

Available values: trace8, …, trace1, debug, info, notice, warn,

error, crit, alert, emerg.

It is also possible to configure the log level for particular modules, e.g.

“LogLevel info ssl:warn”

LogLevel warn

Include module configuration:

IncludeOptional mods-enabled/.load
IncludeOptional mods-enabled/

Include list of ports to listen on

Include ports.conf

Sets the default security model of the Apache2 HTTPD server. It does

not allow access to the root filesystem outside of /usr/share and /var/www.

The former is used by web applications packaged in Debian,

the latter may be used for local directories served by the web server. If

your system is serving content from a sub-directory in /srv you must allow

access here, or in any related virtual host.

Options FollowSymLinks AllowOverride None Require all denied

<Directory /usr/share>
AllowOverride None
Require all granted

<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted

#<Directory /srv/>

Options Indexes FollowSymLinks

AllowOverride None

Require all granted


AccessFileName: The name of the file to look for in each directory

for additional configuration directives. See also the AllowOverride


AccessFileName .htaccess

The following lines prevent .htaccess and .htpasswd files from being

viewed by Web clients.

<FilesMatch “^.ht”>
Require all denied

The following directives define some format nicknames for use with

a CustomLog directive.

These deviate from the Common Log Format definitions in that they use %O

(the actual bytes sent including headers) instead of %b (the size of the

requested file), because the latter makes it impossible to detect partial


Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.

Use mod_remoteip instead.

LogFormat “%v:%p %h %l %u %t “%r” %>s %O “%{Referer}i” “%{User-Agent}i”” vhost_combined
LogFormat “%h %l %u %t “%r” %>s %O “%{Referer}i” “%{User-Agent}i”” combined
LogFormat “%h %l %u %t “%r” %>s %O” common
LogFormat “%{Referer}i -> %U” referer
LogFormat “%{User-agent}i” agent

Include of directories ignores editors’ and dpkg’s backup files,

see README.Debian for details.

Include generic snippets of statements

IncludeOptional conf-enabled/*.conf

Include the virtual host configurations:

IncludeOptional sites-enabled/*.conf

vim: syntax=apache ts=4 sw=4 sts=4 sr noet

#DirectoryIndex index.html index.php /_h5ai/public/index.php


OK, maybe we should look for existing HTTPS configuration with

grep -r SSLCert /etc/apache2