axllent / mailpit

An email and SMTP testing tool with API for developers
https://mailpit.axllent.org
MIT License
5.71k stars 139 forks source link

UI flashing with IIS reverse proxy #131

Closed kustanbruno closed 1 year ago

kustanbruno commented 1 year ago

We are upgrading from mailhog to mailpit. We are trying to use mailpit with IIS as reverse proxy, the configuration seems to be working, but the UI is always refreshing. There are no errors shown in the browser console nor in the output of mailpit. The network tab of the browser shows 2 request repeating:

I was able to replicate the problem in postman too. When connecting via ip address without IIS as reverse proxy, de output looks like this:

image

With IIS as reverse proxy, the output looks like this:

image

Mailhogs websocket endpoint seems to have no problem with the IIS as reverse proxy:

image

How should we troubleshoot this problem?

axllent commented 1 year ago

I can't really say how IIS works, however it appears to be that IIS is closing the websocket connection. Each time the websocket reconnects Mailpit will refresh the messages automatically (so that part is expected). How long does it "hold" the connection for (it appears to immediately disconnect based on what I can see)?

So the issue here is your IIS proxy - if you find out why it's not holding the websocket connection (abnormal closure), then I suspect you'll have your solution. Sorry I can't be more help here, but I really have zero experience in over 15 years with IIS.

doughless commented 1 year ago

I ran into this when trying to set this up at work, too. Apparently, IIS's advanced request routing does not support permessage-deflate: https://serverfault.com/questions/1037407/websocket-based-website-behind-a-reverse-proxy-in-iis https://stackoverflow.com/questions/38933815/iis-8-websockets-with-permessage-deflate

I was able to get it working using the following workaround:

  1. Add HTTP_SEC_WEBSOCKET_EXTENSIONS as an allowed server variable, then
  2. Add the following to your HTTP rewrite rule (I have separate rewrite rules for HTTP and WS, I noticed it only fixed the issue when rewriting the server variable specifically with the HTTP rule):
    <serverVariables>
    <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
    </serverVariables>
axllent commented 1 year ago

Thanks @doughless, I am sure this will help some. Given what you now know, do you think it is fairly easy to document the steps needed in order to set up a proxy for Mailpit using ISS? What I mean is, if I was to get a simple set of instructions of how to set it up on ISS, I could then document this in the Mailpit Wiki for other users to refer to.

doughless commented 1 year ago

@axllent Sure, this is what I put together, hopefully I remembered everything:

Install prerequisites

URL Rewrite 2.1 Application Request Routing 3.0

Enable Application Request Routing proxy

Open IIS Manager, select your server, then open the Application Request Routing Cache feature:

ARR feature

Next, click Server Proxy Settings... Server proxy settings

Finally, check “Enable proxy” and click Apply. Enable proxy

Add server variables

Because Application Request Routing doesn’t work with the permessage_deflate WebSocket extension, you will need to add the HTTP_SEC_WEBSOCKET_EXTENSIONS server variable to URL Rewrite to allow your rewrite rules to remove the Sec-WebSocket-Extensions header value.

To do this, open IIS Manager, select your website, and open the URL Rewrite feature: URL Rewrite

Then click on View Server Variables... and add a server variable named HTTP_SEC_WEBSOCKET_EXTENSIONS: View server variables http_sec_websocket_extension

You can then close IIS Manager; you will need to manually add the URL Rewrite rules to your web.config, because URL Rewrite's UI doesn't allow setting server variables to an empty string value.

Configure URL Rewrite rules

Edit the web.config for your website, and add the following rewrite rules:

<configuration>
    <system.webServer>
        <rewrite>
            <rule name="MailPit Reverse Proxy" stopProcessing="true">
                <match url="^(MP_WEBROOT.*)" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                    <add input="{SERVER_PROTOCOL}" pattern="wss" negate="true" />
                </conditions>
                <action type="Rewrite" url="http://localhost:8025/{R:1}" />
                <serverVariables>
                    <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
                </serverVariables>
            </rule>
            <rule name="MailPit WebSocket Reverse Proxy" stopProcessing="true">
                <match url="^(MP_WEBROOT.*)" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                    <add input="{SERVER_PROTOCOL}" pattern="wss" />
                </conditions>
                <action type="Rewrite" url="ws://localhost:8025/{R:1}" />
            </rule>
        </rewrite>
    </system.webServer>
</configuration>
doughless commented 1 year ago

Thought I'd include a mention to you, @kustanbruno, to see if this helps you.

axllent commented 1 year ago

My apologies for the late reply @doughless - I was away for a few days. That is great, thank you! I have linked it to the Troubleshooting wiki page for now, but will hopefully (one one day not too far away) create and add it directly to a more suitable documentation website for Mailpit :+1:

kustanbruno commented 1 year ago

Hi @doughless, thanks a lot, the configuration works. Your tutorial was really detailed and easy to follow. 👍

I had to add around the two rewrite rules.