Redirecting to https

In my previous post I showed how I used URL Rewrite to act as a reverse proxy for my Subsonic server. Today I plan on using it again to automatically redirect visitors who connect to every site hosted from my server to the https equivalent if they connected via http.

Please note that this is a global rule that will apply to all of your sites. These instructions can apply to just one of your sites by choosing the site rather than the server in IIS Manager in option 1, or the site’s web.config rather than applicationHost.config in the case of option 2.

You will find this to be pretty easy assuming you have already downloaded and installed URL Rewrite in the previous post. I am on IIS 8.5 but this also worked on 7.5; let me know if you are on a different versions and if the instructions work for you.

Option 1 – Using IIS Manager

  1. Open IIS Manager and click on your server in the left pane. Now, in the center pane, double click “URL Rewrite” in the “IIS” section.
  2. In the right pane, under “Actions,” click the “Add rule…” link.
  3. In the center pane select the blank rule. Give the rule a name, I typed “Redirect to https.”
  4. In the Match URL box, accept defaults and type “(*)” (without the quotes) in the pattern textbox.
  5. Under “Conditions,” add a new rule where the condition input is “{HTTPS}” matches the pattern “^OFF$” and click “OK”
  6. In the Action section select “New” the action type “Redirect” and type “{HTTP_HOST}/{R:1}” in the textbox.
  7. Let me know if you have any trouble.

Option 2 – From applicationHost.config

  1. Go to C:\Windows\System32\inetsrv\config and make a copy of applicationHost.config
  2. Open applicationHost.config in a text editor with elevated permissions. I use Notepad++.
  3. Find the section
     <system.webServer>
        <rewrite>
  4. Add or append the following to the <rewrite> section:
    <rewrite>
      <globalRules>
         <rule name="Redirect to https" stopProcessing="true">
           <match url="(.*)" />
           <conditions>
             <add input="{HTTPS}" pattern="^OFF$" />
           </conditions>
           <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
         </rule>
       </globalRules>
     </rewrite>
  5. Save and test. Let me know how the instructions worked for you.

Using IIS to reverse proxy Subsonic

In my previous post I described how to update Subsonic’s default certificate to use a valid certificate issued to my own domain. Although this solves many of the problems with Subsonic’s https implementation, it doesn’t solve all of them. Subsonic’s Jetty server is configured to use a pretty bad cipher. My instance failed SSL Lab’s Server Test. I have found some instructions on how to specify more secure settings, but doing so would require me to repeat the steps each time I updated Subsonic.

Not only does adding my own certificate not solve all the problems with Subsonic, it creates new ones. Adding yet another customization to my server bothers me. I enjoy learning new things but repeating a custom install process over and over is the hallmark of slop: It leads to errors, introduces complexity, lessens maintainability, and causes work. I wouldn’t accept this professionally so why would I do it personally?

A better solution to secure Subsonic on a home windows server is to route traffic through IIS. This has many advantages in my circumstance. I use my home server to host other services besides Subsonic so I have to use nonstandard ports if I want to host a secure blog, Subsonic, and a secure webcam from the same IP. By using IIS as a reverse proxy, IIS can handle the security and route unsecured traffic to these other services. (As an aside, I recall this is how the NSA hacked Google. Though you might log in to gmail securely, once you were logged in communication between Google servers was unsecured. This unsecured communication was what was tapped.) This means that now I need to support just one certificate on IIS rather than on each service independently. Additionally, I can access these other services through standard addressing, i.e. timkelley.com/subsonic rather than timkelley.com:4043. The disadvantages are that 1, I have introduced a single point of failure and 2, I have concentrated SSL processing requirements onto my server away from the distributed services (like my webcams). I am OK with this for a home server which is chronically underworked (processing power is cheap) and not critical.

In my next post I will configure IIS as a reverse proxy for Subsonic so I can begin to use standard ports for all of my various secure services.

Updating Subsonic to Use LetsEncrypt Certificate

Configuring Subsonic to use https is relatively easy and is a necessary first step for a server connected to the Internet. There are many problems with Subsonic’s native implementation of https, however:

  • The certificate is shared across all instances of Subsonic (i.e. My certificate is exactly the same as yours)
  • The certificate, not being associated with the domain name of your server, causes that annoying warning messages in browsers that have to be clicked through.
  • The cipher Jetty uses (Jetty is the server Subsonic is hosed from on your machine) is insecure

The first and second bullet points can be addressed by using a valid certificate. This post talks about configuring subsonic to use a valid certificate.

Assumptions

  1. Your Subsonic server is located on a Windows box
  2. You already own a domain name and your Subsonic instance is reachable through that domain name
  3. You have installed a LetsEncrypt certificate to IIS
  4. You have an unzipping program that can unpack a .jar I used 7-zip.

Step 1 – Prepare for the change

Shut down subsonic and make a backup of \Program Files (x86)\Subsonic (I just copied the entire folder). Do this so that if you make a wrong step, or my steps don’t work for you, you can recover.

Step 2 – Export the certificate

Export your certificate to a format that Subsonic needs. Instructions adapted from https://www.sslshopper.com/move-or-copy-an-ssl-certificate-from-a-windows-server-to-another-windows-server.html

Windows 7 Instructions

  1. Click on the Start menu and click Run.
  2. Type in mmc and click OK to the warning message.
  3. Click on the File menu and click Add/Remove Snap-in…
  4. Click on the Add Double-click on Certificates.
  5. Click on Computer Account and click Next.
  6. Leave Local Computer selected and click Finish.
  7. Click OK.
  8. Click the triangle next to Certificates in the left pane, the triangle next to the Personal folder and click on the Certificates Right-click on the certificate you would like to export and select All Tasks and then Export…
  9. In the Certificate Export Wizard click Next.
  10. Choose “Yes, export the private key” and click Next.
  11. Click the bullet “Personal Information Exchange – PKCS #12 (.pfx)” and then the checkbox next to “Include all certificates in the certification path if possible” and click Next.
  12. Enter “subsonic” as the password and confirm it.
  13. Click Browse and navigate to your desktop. For file name type “subsonic.pkcs12” and select “All Files” for file type. Click Save.
  14. Click Finish.

If the file on your desktop has a .pfx extension you likely forgot to change the file type to “All Files” in step 13. A .pfx file and a .pkcs12 file are the same for our purposes and you can change the extension without issue.

Step 3 – Update Subsonic’s keystore

The keystore is where the Subsonic’s generic certificate is packaged for use by the application. It is a Java-world thing. Since you have Java on your server since you are running Subsonic, you have the tools you need to manipulate the keystore.

  1. Locate the Jar file we will be manipulating “subsonic-booter-jar-with-dependencies.jar”. Mine was located at “C:\Program Files (x86)\Subsonic\subsonic-booter-jar-with-dependencies.jar”
  2. Copy that file to the desktop. This was required for me since I could not edit the file when it was in Program Files.
  3. Open the file with 7-zip.
  4. In the now open archive, copy a file called “subsonic.keystore” to your desktop.
  5. Locate the app bundled with Java called “keytool” Mine was located at “C:\Program Files (x86)\Java\jre1.8.0_60\bin\keytool”
  6. Open an elevated command prompt and change to your desktop directory as your current working directory. From there, run the keytool executable with the following parameters: keytool -list -v -keystore subsonic.pkcs12 -storetype pkcs12 For instance, I ran: “C:\Program Files (x86)\Java\jre1.8.0_60\bin\keytool” -list -v -keystore subsonic.pkcs12 -storetype pkcs12
  7. The previous command will scroll through a lot of lines. Towards the top you will find the certificate’s We need that for the next step.
  8. Adding the alias to the following command, run this in the same elevated console: >”C:\Program Files (x86)\Java\jre1.8.0_60\bin\keytool” -importkeystore -srckeystore subsonic.pkcs12 -destkeystore subsonic.key
    etype PKCS12 -srcstorepass subsonic -srcalias {Alias Here} -destalias subsonic
  9. Use “subsonic” as the password when prompted
  10. Replace keystore in the opened 7-zip archive with the new subsonic.keystore
  11. Close the archive and Copy or Move “subsonic-booter-jar-with-dependencies.jar” on your desktop back to where it came from in step 1. Mine was C:\Program Files (x86)\Subsonic\subsonic-booter-jar-with-dependencies.jar

Step 4 – Cleaning Up and Troubleshooting

Restart the Subsonic service. Once the service is back up (this may take some time depending on how large your collection is), navigate to your Subsonic secure URL in your browser. You should note that you do not have to acknowledge a bad certificate to continue to your login page and you have the lock symbol.

This worked for me the first time so I don’t have any troubleshooting to share. If anyone comments with problems I will update the post here.

Implementing a reverse proxy in IIS 8.5

In my previous post I contrasted using Subsonic’s built in secure server to answer requests from the Internet versus using IIS to proxy those requests. If you want to use IIS to proxy Subsonic requests, here is how I set it up on IIS 8.5. Since the biggest reason to do this is to implement a more robust ssl architecture than Subsonic’s native implementation, I am also assuming you have configured IIS with a valid certificate.

Part 1 – Configure IIS as a Reverse Proxy

  1. Add URL Rewrite and Application Request Routing to IIS via the web platform installer.
  2. Start up IIS Manager and select your server name in the left panel (not the site name). You should see both URL Rewrite and Application Request Routing Cache in the “IIS” section of the center pane. Open “Application Request Routing Cache.” (If you don’t, try quitting IIS Manager and loading it back up again.)
  3. Once that opens, in the right panel’s “Proxy” section, select “Server Proxy Settings…”
  4. In the center panel, check “Enable Proxy.” Leave everything else in the default state and click “Apply.”
  5. Under the “Advanced Routing” section in the right pane, click on the “URL Rewrite…” link.
  6. When the URL Rewrite panel opens click on the “Add Rule…” link in the right pane. Now in the center pane select “Blank Rule” from the “Inbound rules” section and click “OK”.
  7. Give the inbound rule a name. I called mine “Subsonic Reverse Proxy.”
  8. Set the pattern to “subsonic(.*)” (without the quotes) in the “Match URL” section.
  9. In the “Action” box, set “Rewrite URL” to “http://localhost:8080/{R:0}” and click “Apply.”
  10. Type in your domain followed by “/subsonic” in a browser, i.e. yourdomain.com/subsonic, you will see the following error:
    502 - Web server received an invalid response while acting as a gateway or proxy server.
  11. This is the response you want. We haven’t configured Subsonic to catch the request yet.

Part 2 – Configure Subsonic

  1. Open the Subsonic Control Panel and click the “settings” tab.
  2. Set your port number to whatever you specified in step 9, above. My example used 8080.
  3. Uncheck “Enable https…”
  4. Change the “Context Path” to “/subsonic” in the dropdown.
  5. Open the “Status” tab and click “stop,” wait for Subsonic to stop and “Start” and wait for the server to start.
  6. Test your access by going to first “http://localhost:8080/subsonic” (or whatever port you specified). If subsonic comes up, try “https://yourdomain/subsonic” and ensure IIS is proxying your request appropriately.

Apply one Let’sEncrypt certificate to multiple sites on IIS 8.5

The following are the steps that worked for me to get just-created websites up with SSL. I had already created the sites in IIS manager but I would probably add the sites directly to applicationHost.config next time.  These instructions assume you have multiple sites on a server you want to sign using Server Name Indication which is available in IIS 8.5.

  1. From an elevated command prompt on your server go to where you unzipped LetsEncrypt-win-simple and type
    letsencrypt.exe --san
  2. Type ‘S’ to create a single SAN certificate for multiple sites.
  3. Type the site ids for the sites that should be included in the SAN certificate.
  4. Select ‘y’ or ‘n’ depending on whether you want the certificate to update only when you are logged as the user you are currently running these commands under or if you would like to specify a service account.
  5. To update your host headers to consume the SAN certifcate, using an elevated command prompt, go to “C:\Windows\System32\inetsrv\config” and make a copy of applicationHost.config. Now open the original with an elevated text editor (I use notepad++) and find the “<bindings>” section for each of your sites so it looks like the following (replacing yourdomain.com with your domain names):
    <bindings>
      <binding protocol="http" bindingInformation="*:80:yourdomain.com" />
      <binding protocol="http" bindingInformation="*:80:www.yourdomain.com" />
      <binding protocol="https" bindingInformation="*:443:yourdomain.com" sslFlags="1"/>
      <binding protocol="https" bindingInformation="*:443:www.yourdomain.com" sslFlags="1"/>
    </bindings>
    
  6. Restart IIS so the changes take effect.
  7. Ensure that you have properly allowed and / or forwarded port 443 in your firewall.
  8. Test and comment on this post if the instructions worked (or if they didn’t).

Troubleshooting

  1. I reproduced these steps on IIS 8.5 (I originally wrote them for my IIS 7.5 server).  Between steps 3 and 4, above, the Let’s Encrypt application (LetsEncrypt-win-simple) writes a file to your website’s files and then prompts their servers to try to read those files. I got a 401 error.
    To fix this I have to back up a bit in my explanation.  When I create my sites in IIS I immediately go to the file system and in the root folder for that site I give Read/Write access to the AppPool Identity for the site. (i.e. IIS AppPool\timkelley.com). That being said, what caused the 401 error is I didn’t set Anonymous Authentication to the application pool identity. The default is IUSR and that account didn’t have access to my folders.
  2. If you find your certificate is not renewing you can run the following manually:
    path_to_letsencrypt>letsencrypt.exe --renew