Placing Apache reverse proxy in front of Security Onion

Security Onion prefers to think that it's talking to the world, not a proxy. But you can do it.

It took me awhile to get this working because I was also trying to get Apache Basic Authentication working. Alas, Security Onion is so complex that I was only able to get Authentication working smoothly for the front-door portion so far, so I'm leaving that information out for now.

Note that I had to configure Security Onion during install with the complete FQDN ("securityonion.example.com") that would be visible to the Internet, even though it does not talk directly to the internet.

Trying to access the internal Security Onion server via IP Address or via hostname, etc., did not work. I tried all these options. Using the FQDN in both the Security Onion server and the reverse proxy server is the only way that worked.

Note I used /etc/hosts on the Apache server to redirect it to talk to the internal "securityonion.example.com" Security Onion server, which worked nicely, since /etc/hosts overrides any DNS lookup. So when you connect to Apache on the front end (i.e. using public DNS) to the external IP Address, it then internally uses the same domain name to talk to an internal IP Address. Just add a single line to /etc/hosts and it will work.

[UPDATE: This worked as described once, but I found later on another installation that in the /etc/hosts file "127.0.1.1" needs to point to the webserver hostname, and "127.0.0.1" needs to point to "localhost". I also had to add a conf.d file using echo 'ServerName <myhostname>' | sudo tee /etc/apache2/conf-available/fqdn.conf as described in this AskUbuntu answer. While that answer gave me the technique to use, this answer on AskUbuntu gave me the background information I needed to understand the issue. So, you may or may not need to do this part. Note, along the way of resolving this, I also added the FQDN of the webserver itself in /etc/hosts -- pointing to its own external IP Address -- as well as the line for the Security Onion FQDN pointing to the internal IP as described in the preceding paragraph. These changes may or may not have contributed to my eventual success. If you need to pursue these tips, see the end of this article for an example /etc/hosts.]

So let's take a look at what you need to do in Apache to configure it as a reverse proxy for Security Onion.

<VirtualHost *:443>
    ServerName example.com

    ServerAdmin webmaster@example.com

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLProxyEngine on

    # Disable checking CN til we get certs working properly in SO
    # Temporary, but safe because external facing traffic is encrypted
    SSLProxyCheckPeerCN off

    ProxyPreserveHost on
    ProxyRequests off
    ProxyPass "/" https://example.com/
    ProxyPassReverse "/" https://example.com/

    RewriteEngine on
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "wss://example.com/$1" [P,L]
    #RewriteRule ^/?(.*) "wss://example.com/%{REQUEST_URI}" [P,L]

    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>

I first got it working without the Rewrite/Websocket stanza. It worked, but Security Onion could not connect to "the manager." It nicely posted a message saying that, and behind the scenes (visible in developer tools/console within the browser which is accessible by F12 in many browsers), it was throwing an error like the following:

app.js?v=2.3.60:509 WebSocket connection to 'wss://example.com/ws' failed: 
openWebsocket @ app.js?v=2.3.60:509
app.js?v=2.3.60:228 2021-07-09T14:05:43-05:00 | WebSocket failure: undefined
app.js?v=2.3.60:228 2021-07-09T14:05:43-05:00 | WebSocket closed, will attempt to reconnect
app.js?v=2.3.60:228 2021-07-09T14:05:57-05:00 | WebSocket connecting to wss://example.com/ws

Adding the websocket stanza (the text with RewriteRule ^/?(.*) "wss://example.com/$1" [P,L]) fixed this problem.

That commented line in the Rewrite section is another way of accomplishing the preceding line; I left it in because at one point in the journey it worked while the preceding line did not. That was probably a cache issue, but I left this in just in case you run into similar problems. Also, leaving off the trailing "/" in that same line was effective at one point, but the config above currently works, so hopefully you don't have to tinker with the little things like I did while trying to find this solution.

I won't go into enabling modules ("sudo a2enmod proxy_wstunnel"), running LetsEncrypt, etc. Hopefully if this post is interesting to you at all, you already know or can figure out that part yourself. If you want more, here's a good link from ServerLab that goes into proxying with wstunnel in more detail.

Have fun.

[UPDATE: Here is the sample /etc/hosts mentioned in the update above.]

Sample /etc/hosts for a Debian-type webserver in front of Security Onion:

# use the following two lines to add the ServerName to Apache at global level
# echo 'ServerName myhostname' | sudo tee /etc/apache2/conf-available/fqdn.conf
# sudo a2enconf fqdn
# use the following two lines to configure localhost in a debian-based system
127.0.0.1 localhost
127.0.1.1 myhostname

# this should be the external ip address and full FQDN
# for the current web server
160.232.331.240 myhostname.mydomain.com

# this should be the internal ip address and full FQDN
# for the security onion server
10.101.0.9 securityonion.mydomain.com

Posted in Developing Software on Jul 09, 2021

Post New Comment