Apache Reverse Proxy

From Universal Devices, Inc. Wiki

It is possible to configure Apache to perform a reverse proxy function to the ISY - including support for websockets. It's not completely useful - since the SOAP subscription used by the admin console and Mobilinc is not supported by Apache. This configuration works well with Agave - and allows a very speedy SSL connection to be achieved, once you add SSL to the virtual.

Apache needs to have the following modules enabled:

  • mod_proxy_wstunnel
  • mod_proxy
  • mod_proxy_http
  • mod_proxy_html
  • mod_headers

Please note: mod_proxy_wstunnel is only (officially) available for Apache 2.4. It has been backported to Apache 2.2 - but you'll have to compile it yourself. See this article for details on how to do this.

First, some assumptions.... You have a SSL virtualhost (lights.domain.com) that is going to serve as a proxy to your ISY (IP is 192.168.1.2) using HTTP. The directory on your server assigned is /var/www/lights. You can place your own pages in /var/www/lights (for instance, the websocket example). This example forces authentication - and injects the correct authorization header when presented to ISY. This means you can use different credentials for this site - or even multiple user accounts.

Make sure to set the Authorization header to be correct for your ISYs credentials. This needs to be in the format 'username:password' and then base64 encoded. You can (probably) generate the needed header value with the command line:

echo -n "user:password" | base64

(replace user and password with your ISY username and password)

<VirtualHost *:80>
  ServerAdmin webmaster@lights.domain.com
  DocumentRoot /var/www/html
  ProxyRequests Off
  ProxyPreserveHost On
  KeepAlive On
  KeepAliveTimeout 5000
  ProxyVia Off
  SetEnv force-proxy-request-1.0 1
  SetEnv proxy-nokeepalive 1
#  SetEnvIf Request_URI ^/{SECURE_RANDOM_STRING}/ noauth=1
  <Proxy *>
    Require host lights.domain.com
    AuthName "Authentication Required"
    AuthType Basic
    AuthUserFile /etc/htpasswd-isy
    Order deny,allow
    Satisfy any
    Deny from all
    require valid-user
    Allow from env=noauth
  </Proxy>
  RequestHeader set Authorization "Basic xxxxxxxxxxxxxxxxx"
#  ProxyPass /{SECURE_RANDOM_STRING} http://192.168.1.2/rest
#  ProxyPassReverse /{SECURE_RANDOM_STRING} http://192.168.1.2/rest
  ProxyPass "/rest/subscribe" "ws://192.168.1.2/rest/subscribe" retry=4
  ProxyPass "/rest" "http://192.168.1.2/rest"
  ProxyPass "/services" "http://192.168.1.2/services"
  ProxyPass "/WEB" "http://192.168.1.2/WEB"
  ProxyPass "/USER" "http://192.168.1.2/USER"
  ProxyPassReverse "/rest/subscribe" "ws://192.168.1.2/rest/subscribe" retry=4
  ProxyPassReverse "/rest" "http://192.168.1.2/rest"
  ProxyPassReverse "/services" "http://192.168.1.2/services"
  ProxyPassReverse "/WEB" "http://192.168.1.2/WEB"
  ProxyPassReverse "/USER" "http://192.168.1.2/USER"
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  ErrorLog ${APACHE_LOG_DIR}/error.log
</VirtualHost>

Create a .htpasswd-isy file:

htpasswd -c /etc/htpasswd-isy username

Set your proxy authentication password when prompted.

Place the following .htaccess file into /var/www/html (or wherever the web root directory is!):

AuthType Basic
AuthName "Authentication Required"
AuthUserFile "/etc/htpasswd-isy"
Require valid-user

This will proxy certain paths back to the ISY - with the exceptions of the REST endpoints, the /WEB and /USER paths (allowing UDajax and HAD to function, as well as custom web space on the ISY itself).

You should wrap this in SSL! Otherwise - you are sending password in plain text. This is beyond the scope of this article though. If you are successful with SSL, you can allow the IFTTT Maker channel to make requests to the REST API in a secure way. Visit https://www.grc.com/passwords.htm or https://www.safetydetectives.com/password-meter/ and pull a random alpha-numeric string to replace {SECURE_RANDOM_STRING} with - and then uncomment the three lines. This will allow IFTTT to make requests to https://lights.domain.com/{SECURE_RANDOM_STRING}/ (instead of https://lights.domain.com/rest) without needing any further authentication.