Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS URL Rewrite ~ Rewriting Paths to Ports

My situation is as follows:

We have an array of CI services, such as TeamCity, YouTrack and OctopusDeploy on a single server. Currently, we are accessing all of these via DNS Name plus port, e.g.:

TeamCity:      http://server.company.com
YouTrack:      http://server.company.com:1234
OctopusDeploy: http://server.company.com:5678/octopus

I'm currently adjusting that so we can access these services via https. For that purpose, I've set up an IIS Server as a Reverse Proxy by using IIS URL Rewrite to handle SSL authentication. This already works, and I can now access TeamCity via https://server.company.com

However, while I'm at it, I would also like to use IIS URL Rewrite to beautify the addresses, and get rid of the need to memorize port numbers. What I want to achieve are the following redirects:

https://server.company.com          -> http://server.company.com (already working)
https://server.company.com/youtrack -> http://server.company.com:1234
https://server.company.com/octopus  -> http://server.company.com:5678/octopus

I have already tried adding the following rules:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="ReverseProxyInboundRule2" stopProcessing="true">
                    <match url="^(https://server.company.com/youtrack)(.*)$" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="http://server.company.com:1234/{R:2}" />
                </rule>
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAny" trackAllCaptures="false">
                        <add input="{PATH}" pattern="youtrack" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="http://server.company.com/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

...and tested it in the IIS Manager, which correctly recognizes the rules and conditions, and also returns the correct backwards rules.

However, when I try to access https://server.company.com/youtrack, I am redirected to http://server.company.com/youtrack instead of http://server.company.com:1234 as I intended. It's like the ReverseProxyInboundRule2 is not evaluated at all.

I'm sure there's a logical explanation for this and a way to make it work. I just can't see it on my own. What can I do to make this work?


UPDATE 30-Mar-2018:

Okay, so I figured out a configuration that partially works. It goes as follows:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="Reverse Proxy to TeamCity" stopProcessing="true">
                    <match url="^teamcity/(.*)" />
                    <action type="Rewrite" url="http://server.company.com/{R:1}" />
                </rule>
                <rule name="Reverse Proxy to YouTrack" stopProcessing="true">
                    <match url="^youtrack/(.*)" />
                    <action type="Rewrite" url="http://server.company.com:1234/issues/{R:1}" />
                </rule>
                <rule name="Reverse Proxy to Hub" stopProcessing="true">
                    <match url="^hub/(.*)" />
                    <action type="Rewrite" url="http://server.company.com.de:5678/hub/{R:1}" />
                </rule>
                <rule name="Reverse Proxy to UpSource" stopProcessing="true">
                    <match url="^upsource/(.*)" />
                    <action type="Rewrite" url="http://server.company.com.de:9876/{R:1}" />
                </rule>
                <rule name="Reverse Proxy to Octopus" stopProcessing="true">
                    <match url="^octopus/(.*)" />
                    <action type="Rewrite" url="http://server.company.com:5432/octopus/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

This configuration redirects the requests as follows:

https://server.company.com          -> http://server.company.com
https://server.company.com/youtrack -> http://server.company.com:1234/issues/
https://server.company.com/hub      -> http://server.company.com:5678/hub/
https://server.company.com/upsource -> http://server.company.com:9876
https://server.company.com/octopus  -> http://server.company.com:5432/octopus/

This works perfectly for Octopus.

On Hub, there is a "Connection is not secure" notification next to the address, saying that "Parts of the web site (such as images) are not secure". Going into the page info, it says in the Security tab under Technical Details that the Connection is only Partially Encrypted. However, the rest of the page appears to be working fine.

TeamCity and YouTrack are more whimsical. On Chrome, TeamCity works fine (for a while until it gets a random disconnect) but YouTrack delivers a 404 error, while on Firefox both TeamCity and YouTrack are displayed in an unusable "text-only" form.

UpSource, meanwhile, delivers a blank page on either browser.

I've cross-tested this on various browsers and machines and came to the conclusion that TeamCity, YouTrack and Hub only "sort of" work if I am already logged into the http versions of those services on those servers. If I am not logged in, then I get 404 errors for TeamCity and YouTrack. As for Hub, I get a 405 error on trying to log in with a "POST-Method not supported" message.

So the basic result of my above written configuration on a clean slate is as follows:

TeamCity: 404 Error
YouTrack: 404 Error
Hub:      405 Error on login
UpSource: Blank Page
Octopus:  Working
like image 352
Kira Resari Avatar asked Oct 18 '25 16:10

Kira Resari


1 Answers

Okay, after a lot of back and forth, I figured out a working configuration for all of these services:

  • Set up a http IIS Reverse proxy
    • The following modules need to be installed in IIS:
      • URL Rewrite (via https://www.iis.net/downloads/microsoft/url-rewrite)
      • Application Request Routing (via https://www.iis.net/downloads/microsoft/application-request-routing)
      • WebSocket Protocol (va Server Manager: Web Server (IIS) > Web Server > Application Development > WebSocket Protocol)
      • Dynamic Content Compression (via Server Manager: Web Server (IIS) > Web Server > Performance > Dynamic Content Compression)
    • Create a website for the URL redirect
    • Create a https binding for that website using a valid certificate
    • Disable Dynamic Content Compression under [Server] > Compression
    • Go to [Server] > Application Request Routing > Server Proxy Settings and select ☑ “Enable Proxy”
    • Make sure the following values are set:
      • HTTP Version: Pass Through
      • Time-out: 120
      • Preserve client Ip for the following header: X-Forwarded-For
      • Memory Cache Duration: 60
      • Query String Support: Ignore Query String
      • Response Buffer: 4096
      • Response Buffer Threshold: 0
  • Set up the URL rewrite and related settings
    • Add the following server variables in [Server] > URL Rewrite > View Server Variables
      • HTTP_X_FORWARDED_HOST
      • HTTP_X_FORWARDED_SCHEMA
      • HTTP_X_FORWARDED_PROTO
    • Configure the web.config as follows:

web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="Reverse Proxy to TeamCity" stopProcessing="true">
                    <match url="^teamcity(.*)" />
                    <action type="Rewrite" url="http://server.company.com{R:1}" />
                </rule>
                <rule name="Reverse Proxy to Hub" stopProcessing="true">
                    <match url="^hub(.*)" />
                    <action type="Rewrite" url="http://server.company.com:8082/hub{R:1}" />
                    <serverVariables>
                        <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
                        <set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
                        <set name="HTTP_X_FORWARDED_PROTO" value="https" />
                    </serverVariables>
                </rule>
                <rule name="Reverse Proxy to YouTrack" stopProcessing="true">
                    <match url="^youtrack(.*)" />
                    <action type="Rewrite" url="http://server.company.com:8080/youtrack{R:1}" />
                    <serverVariables>
                        <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
                        <set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
                        <set name="HTTP_X_FORWARDED_PROTO" value="https" />
                    </serverVariables>
                </rule>
                <rule name="Reverse Proxy to UpSource" stopProcessing="true">
                    <match url="^upsource(.*)" />
                    <action type="Rewrite" url="http://server.company.com:8081/upsource{R:1}" />
                    <serverVariables>
                        <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
                        <set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
                        <set name="HTTP_X_FORWARDED_PROTO" value="https" />
                    </serverVariables>
                </rule>
                <rule name="Reverse Proxy to Octopus" stopProcessing="true">
                    <match url="^octopus(.*)" />
                    <action type="Rewrite" url="http://server.company.com:8888/octopus{R:1}" />
                </rule>
                <rule name="Reverse Proxy to Collaboration General" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="http://server.company.com/{R:1}" />
                </rule>
            </rules>
        </rewrite>
        <security>
            <requestFiltering>
                <requestLimits maxAllowedContentLength="300000000" maxUrl="6144" maxQueryString="4096" />
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>
  • Configure Hub, YouTrack and UpSource as follows
    • NOTE: The commands beginning with hub.bat / youtrack.bat / upsource.bat need to be performed on the respective file in [Installation Directory]\bin of the respective service.

cmd:

upsource.bat stop
youtrack.bat stop
hub.bat stop

hub.bat configure --listen-port 8082 --base-url https://server.company.com/hub
youtrack.bat configure --listen-port 8080 --base-url=https://server.company.com/youtrack--hub-url=https://server.company.com/hub/hub
upsource.bat configure --listen-port 8081 --base-url=https://server.company.com/upsource --hub-url=https://server.company.com/hub/hub

hub.bat start
youtrack.bat start
upsource.bat start --J-Dbundle.websocket.compression.enabled=false

NOTE: I don't know why, but Hub appends an extra /hub after its base address, that's why the hub-url setting for UpSource ends with /hub/hub.

After that, all I needed to do was add the redirection URLs to the list of allowed redirection URLs for the services and change the basis urls for TeamCity and OctopusDeploy in Hub > Settings > Services, and now it all works perfectly.

Well, almost perfectly. Whenever the server gets restarted I need to manually restart UpSource since I've not yet figured out a way to register upsource as a service with the --J-Dbundle.websocket.compression.enabled=false parameter, but apart from that, everything works perfectly.

like image 88
Kira Resari Avatar answered Oct 20 '25 07:10

Kira Resari



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!