Using IIS as a reverse proxy in front of Apache/SVN

93 views
Skip to first unread message

Daniel Sahlberg

unread,
Jun 9, 2021, 2:25:14 AM6/9/21
to Subversion
Hi,

We are using VisualSVN server (basically Apache 2.4.48 and Subversion 1.14.1 on Windows) on https://svn.companyname.tld, listening on port 443. Currently this is on a separate server. I need to consolidate the servers and would like to move Subversion to another server already running IIS (serving multiple sites on both port 80 and 443).

My thinking is that IIS should listen for the new hostname, do SSL offloading and forward the traffic to 127.0.0.1:[some new port for Apache]. I would like to avoid publishing the new port for Apache, since that would mean to relocate all existing working copies.

Does anyone have experience in using IIS as reverse proxy in front of Apache?

Kind regards,
Daniel Sahlberg

Daniel Shahaf

unread,
Jun 9, 2021, 8:24:01 PM6/9/21
to Daniel Sahlberg, Subversion
Not what you asked, but running the test suite under a reverse proxy
configuration might be informative.

Cheers,

Daniel

Daniel Sahlberg

unread,
Jun 10, 2021, 1:44:39 AM6/10/21
to Daniel Shahaf, Subversion
Thanks! I will try to find some time to look at it.

Thinking of it, I guess the question could be generalized as: Is it possible to run Subversion behind /any/ kind of reverse proxy?

Kind regards,
Daniel

Branko Čibej

unread,
Jul 13, 2021, 9:44:29 AM7/13/21
to us...@subversion.apache.org
On 10.06.2021 07:44, Daniel Sahlberg wrote:
> Den tors 10 juni 2021 kl 02:23 skrev Daniel Shahaf
> <d...@daniel.shahaf.name <mailto:d...@daniel.shahaf.name>>:
>
> Daniel Sahlberg wrote on Wed, Jun 09, 2021 at 08:18:04 +0200:
> > Hi,
> >
> > We are using VisualSVN server (basically Apache 2.4.48 and
> Subversion
> > 1.14.1 on Windows) on https://svn.companyname.tld
> <https://svn.companyname.tld>, listening on port 443.
> > Currently this is on a separate server. I need to consolidate
> the servers
> > and would like to move Subversion to another server already
> running IIS
> > (serving multiple sites on both port 80 and 443).
> >
> > My thinking is that IIS should listen for the new hostname, do SSL
> > offloading and forward the traffic to 127.0.0.1:[some new port
> for Apache].
> > I would like to avoid publishing the new port for Apache, since
> that would
> > mean to relocate all existing working copies.
> >
> > Does anyone have experience in using IIS as reverse proxy in
> front of
> > Apache?
>
> Not what you asked, but running the test suite under a reverse proxy
> configuration might be informative.
>
>
> Thanks! I will try to find some time to look at it.
>
> Thinking of it, I guess the question could be generalized as: Is it
> possible to run Subversion behind /any/ kind of reverse proxy?

Yes, it is possible. Subversion doesn't do anything magic. Some time
ago, many reverse/caching proxies didn't understand some of the
DAV-related HTTP methods that Subversion uses. I'd hope this is no
longer the case ... especially as, AFAIK, IIS can be a WebDAV server.

-- Brane

Daniel Sahlberg

unread,
Jul 19, 2021, 5:36:46 PM7/19/21
to Branko Čibej, Subversion
Thank you Brane!

I finally found some time to test it out and it worked first time.

For reference, in case someone else face a similar problem:
* IIS is listening on port 80 and 443, these ports are exposed externally.
* VisualSVN Server (ie, Apache HTTPD + Subversion + some proprietary stuff) is listening on port 81 for HTTP only
* I configured a site in IIS with bindings on port 80 and 443, with IIS' setting "Require SSL" (any traffic on port 80 will give a 403 error message so the user can update the URL).

Now IIS is doing SSL offloading and forwarding the (unencrypted) traffic internally to VisualSVN Server.

I've so far just made some minor tests, will migrate our production repositories and do more detailed testing in the next few days.

Kind regards,
Daniel Sahlberg


 

Mark Phippard

unread,
Jul 19, 2021, 6:22:08 PM7/19/21
to Daniel Sahlberg, Branko Čibej, Subversion
Try the svn copy command and see if that works. It usually will not
until/unless the HTTP "Destination" header is rewritten. You can do
this on the Apache side if IIS cannot do it.

Mark

Mark Phippard

unread,
Jul 19, 2021, 6:38:11 PM7/19/21
to Daniel Sahlberg, Subversion
This is the directive we use on the Apache side to rewrite the header:

RequestHeader edit Destination ^https http early

Mark

Daniel Sahlberg

unread,
Jul 19, 2021, 8:12:46 PM7/19/21
to Mark Phippard, Branko Čibej, Subversion
Den tis 20 juli 2021 kl 00:22 skrev Mark Phippard <mark...@gmail.com>:
Try the svn copy command and see if that works. It usually will not
until/unless the HTTP "Destination" header is rewritten. You can do
this on the Apache side if IIS cannot do it.

That was indeed a good catch. This page [1] provided valuable information on how to do it on Apache. I wanted to do as much as possible on the IIS side so I dived deep into the URL Rewrite module.

I finally found that I had to do two separate rewrite rules:
- Catching the requests having an HTTP Destination and switching from https:// to http:// before forwarding the request. To make this work, I had to add HTTP_DESTINATION as an acceptable server variable, see [2].
- Everything else (without setting any HTTP headers).

I hope it is not too much offtopic to paste the relevant part of web.config:

[[[
        <rewrite>
            <rules>
                <clear />
                <rule name="ProxyWithDestination" enabled="true" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTP_DESTINATION}" pattern="https://(.*)" />
                    </conditions>
                    <serverVariables>
                        <set name="HTTP_DESTINATION" value="http://{C:1}" />
                    </serverVariables>
                    <action type="Rewrite" url="http://127.0.0.1:81/{R:1}" />
                </rule>
                <rule name="ProxyRest" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="http://127.0.0.1:81/{R:1}" logRewrittenUrl="true" />
                </rule>
            </rules>
        </rewrite>
]]]

Kind regards,
Daniel Sahlberg


Daniel Sahlberg

unread,
Sep 23, 2022, 2:30:13 AMSep 23
to Subversion, VisualSVN Team
I'm following up on an old e-mail [1] on how to use IIS as a reverse proxy in front of Apache Subversion.

Previously I found found a way to use the URL Rewrite module to forward requests to mod_dav_svn. This was working fine until I tried to access a file with a "+" encoded in the filename.

[[[
$ svn log "https://svn.example.com/svn/repo/file with + in filename.txt"

svn: E170013: Unable to connect to a repository at URL 'https://svn.example.com/svn/repo/file%20with%20+%20in%20filename.txt'

svn: E160013: '/svn/repo/file%20with%20+%20in%20filename.txt' path not found

$
]]]

It turns out that IIS will not accept requests with "+" and will reply with http error 404.11 instead of rewriting the request and forwarding to mod_dav_svn.

A similar problem is described here [2] and IIS can be configured to "allowDoubleEscaping" [3]. With this configuration changed everything worked as expected.

The solution was found by sup...@visualsvn.com (we use their software stack on the server).

The relevant parts of web.config can be found below.

Kind regards,
Daniel Sahlberg



[[[
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="To https" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTPS}" pattern="^OFF$" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" />
                </rule>
                <rule name="ProxyWithDestination" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTP_DESTINATION}" pattern="https://(.*)" />
                    </conditions>
                    <serverVariables>
                        <set name="HTTP_DESTINATION" value="http://{C:1}" />
                    </serverVariables>
                    <action type="Rewrite" url="http://127.0.0.1:81/{R:0}" logRewrittenUrl="true" />
                </rule>
                <rule name="ProxyRest" patternSyntax="ECMAScript" stopProcessing="true">
                    <match url="(.*)" negate="false" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="http://127.0.0.1:81/{R:0}" logRewrittenUrl="true" />
                </rule>
            </rules>
        </rewrite>
        <security>
            <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
]]]

Reply all
Reply to author
Forward
0 new messages