Octopod Mobile iOS + Reverse Proxy

What is the problem?

Hi all, I'm new to Octoprint and I am loving the software. I setup a reverse proxy on my IIS server to create a secure connection to my Octoprint server, which is running on a Jetson Nano, I performed a manual install. I verified using the reverse proxy check that everything was cool, and everything works 100% when using a web browser. However, when using any of the iOS apps, I find that some of the controls work, and others don't. For instance, I can't view the g-code terminal, or see the print progress, nor stop or pause a job. I can start a job from a file no problem. If I connect directly to my homebrewed octoprint server on the Jetson Nano on port 5000 all the features work.

What did you already try to solve it?

Double checked headers, and reverse proxy requirements, everything's ok, works perfectly from a web browser.

Logs (syslog, dmesg, ... no logs, no support)

dmesg nothing of note, clean
syslog:

Jan 15 23:09:51 myserve octoprint[12595]: 2023-01-15 23:09:51,719 - octoprint.server.util.sockjs - INFO - New connection from client: 172.32.8.23:58372#033[0m
Jan 15 23:09:51 myserve octoprint[12595]: 2023-01-15 23:09:51,750 - octoprint.server.util.sockjs - INFO - Client connection closed: 172.32.8.23:58372#033[0m
Jan 15 23:09:51 myserve octoprint[12595]: 2023-01-15 23:09:51,816 - octoprint.server.util.flask - INFO - Passively logging in user myUserName from 172.32.8.23:55796#033[0m
Jan 15 23:09:51 myserve octoprint[12595]: 2023-01-15 23:09:51,817 - octoprint.access.users - INFO - Logged in user: philip#033[0m
Jan 15 23:09:51 myserve octoprint[12595]: #033[31m2023-01-15 23:09:51,819 - octoprint.util.net - ERROR - Error while trying to determine whether 172.32.8.23:55796 is a local address#033[0m
Jan 15 23:09:51 myserve octoprint[12595]: Traceback (most recent call last):
Jan 15 23:09:51 myserve octoprint[12595]: File "/home/pi/OctoPrint/venv/lib/python3.10/site-packages/octoprint/util/net.py", line 125, in is_lan_address
Jan 15 23:09:51 myserve octoprint[12595]: ip = netaddr.IPAddress(address)
Jan 15 23:09:51 myserve octoprint[12595]: File "/home/pi/OctoPrint/venv/lib/python3.10/site-packages/netaddr/ip/init.py", line 305, in init
Jan 15 23:09:51 myserve octoprint[12595]: raise AddrFormatError('failed to detect a valid IP '
Jan 15 23:09:51 myserve octoprint[12595]: netaddr.core.AddrFormatError: failed to detect a valid IP address from '172.32.8.23:55796'

Additional information about your network (Hardware you are trying to connect to, hardware you are trying to connect from, router, access point, used operating systems, ...)

IIS Reverse Proxy (Windows 2022) on Port 443 -> Jetson Nano Running Ubuntu on Port 5000

Just a heads up, I got this sorted out... Turned out that I had to allow the reverse proxy to proxy websocket traffic as well. It's working like a champ now... I'll post something later with the full config in case anyone else is using an IIS Reverse Proxy to front-end all of their sites.

How I was able to figure it out was by enabling debugging for the octoprint log, then comparing connections through the reverse proxy and then directly to the server. When connecting directly to the server I saw multiple websocket connections taking place which weren't apparent when connecting through the proxy.

2 Likes

Struggling with this exact thing right now. If you could post your web.config that would be awesome.

Hi there, happy to, I’m traveling right now, but I’ll be back later this weekend and will post it.

1 Like

Hook me up brotha! :smiley:

Sorry for the delay, I've just been super slammed recently. One of these days if I ever get time again I'll write up a step-by-step guide.

If you have any questions let me know and we can see about connecting on Zoom to go over. I have 2 web.config files, one for handling the actual Octoprint server, and another to deal with the webcam plugin.

Pre-requisites:

  1. Windows IIS
  2. IIS URL Rewrite Tool Installed

web.config - Root Path

  1. Replace all instances of "fqdn.of-your-reverse-proxy.com" with the FQDN for your reverse proxy. This will be the URL that the clients will connect to.

  2. Replace all instances of "fqdn.of-your-octoprint-server.com:5000" with the internal FQDN of your Octoprint server, if using a port other than 5000, then replace that shiznit too...

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <outboundRules>
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
                    <match filterByTags="A, Form, Img" pattern="^http(s)?://fqdn.of-your-octoprint-server.com:5000/(.*)" />
                    <action type="Rewrite" value="http{R:1}://fqdn.of-your-reverse-proxy.com/{R:2}" />
                </rule>
                <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                    <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                    <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                </rule>
                <rule name="RewriteEncodedAnchorTags" preCondition="ResponseIsHtml1">
                    <match pattern="href=(.*?)http://fqdn.of-your-octoprint-server.com:5000/(.*?)\s" />
                    <action type="Rewrite" value="href={R:1}https://fqdn.of-your-reverse-proxy.com/{R:2}" />
                </rule>
                <rule name="RestoreFormElementEncoding" preCondition="ResponseIsHtml1">
                    <match pattern="action=(.*?)http://fqdn.of-your-octoprint-server.com:5000/(.*?)\\" />
                    <action type="Rewrite" value="action={R:1}https://fqdn.of-your-reverse-proxy.com/{R:2}\" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/(.+)" />
                    </preCondition>
                    <preCondition name="NeedsRestoringAcceptEncoding">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
            <rules>
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="http://fqdn.of-your-octoprint-server.com:5000/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="0" />
                    </serverVariables>
                </rule>
            </rules>
        </rewrite>
        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/lost" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>

web.config - /video folder

  1. Create a folder in the root path of the site that's going to reverse proxy to Octoprint, and call it "video".

  2. Replace all instances of "fqdn.of-your-reverse-proxy.com" with the FQDN for your reverse proxy. This will be the URL that the clients will connect to.

  3. Replace all instances of "fqdn.of-your-octoprint-server.com" with the internal FQDN of your Octoprint server.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system. Webserver>
        <rewrite>
            <rules>
                <remove name="ReverseProxyInboundRule1" />
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{QUERY_STRING}" pattern="action=stream" />
                        <add input="{QUERY_STRING}" pattern="action=snapshot" />
                    </conditions>
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="0" />
                    </serverVariables>
                    <action type="Rewrite" url="http://fqdn.of-your-octoprint-server.com:8080/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
                </rule>
            </rules>
            <outboundRules>
                <remove name="RestoreFormElementEncoding" />
                <remove name="RewriteEncodedAnchorTags" />
                <remove name="ReverseProxyOutboundRule1" />
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
                    <match filterByTags="A, Form, Img" pattern="^http(s)?://fqdn.of-your-octoprint-server.com:8080/(.*)" />
                    <conditions />
                    <action type="Rewrite" value="http{R:1}://fqdn.of-your-reverse-proxy.com/{R:2}" />
                </rule>
                <rule name="RewriteEncodedAnchorTags" preCondition="ResponseIsHtml1">
                    <match filterByTags="None" pattern="href=(.*?)http://fqdn.of-your-octoprint-server.com:8080/(.*?)\s" />
                    <conditions />
                    <action type="Rewrite" value="href={R:1}https://fqdn.of-your-reverse-proxy.com/{R:2}" />
                </rule>
                <rule name="RestoreFormElementEncoding" preCondition="ResponseIsHtml1">
                    <match filterByTags="None" pattern="action=(.*?)http://fqdn.of-your-octoprint-server.com:8080/(.*?)\\" />
                    <conditions />
                    <action type="Rewrite" value="action={R:1}https://fqdn.of-your-reverse-proxy.com/{R:2}\" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
    <location path="index.html">
        <system.webServer>
            <httpRedirect enabled="true" destination="https://fqdn.of-your-reverse-proxy.com/lost/?404;https://fqdn.of-your-reverse-proxy.com:443/video/index.html" />
        </system. Webserver>
    </location>
</configuration>

This worked for me, depending on your overall config your mileage may vary, but again, if you have any questions let me know, we can take it offline when we both have time.

1 Like

I got it working, it was missing a few of those server variables. Most appreciated!

I used your config and now I am getting a CSRF error and Cannot figure out how to fix this. any advice?