[{"data":1,"prerenderedAt":53},["ShallowReactive",2],{"$f1gx5kes3oxgcw":3,"recommended":22},{"title":4,"path":5,"date":6,"updated":7,"tags":8,"excerpt":11,"readingMinutes":12,"commentCount":13,"html":14,"comments":15,"next":16,"prev":19},"A secure home gateway on the Raspberry Pi in four parts. Part four, proxying to your devices","\u002F2012\u002F10\u002Fa-secure-home-gateway-on-raspberry-pi_2406\u002F","2012-10-14T09:49:00.002Z","2012-10-14T10:05:46.574Z",[9,10],"hardware","how-to","I have some very nifty devices lying around in my home: A couple of computers A very smart router with the Tomato firmware A Raspberry Pi model B (the only one you can get right now) A Popcorn Hour A200 Besides that, I…",4,0,"\u003Cp>I have some very nifty devices lying around in my home:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>A couple of computers\u003C\u002Fli>\n\u003Cli>A very smart router with the Tomato firmware\u003C\u002Fli>\n\u003Cli>A Raspberry Pi model B (the only one you can get right now)\u003C\u002Fli>\n\u003Cli>A Popcorn Hour A200\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Besides that, I have full control over a domain name (waleson.com.).\u003C\u002Fp>\n\u003Cp>The amount of cool things you can do with this is enormous. However, until yesterday morning, these devices were working with most of their default settings (BOOOORING). Here's how I made it awesome in one evening.\u003C\u002Fp>\n\u003Ch2>Part four, proxying to your devices.\u003C\u002Fh2>\n\u003Col>\n\u003Cli>Part one - \u003Ca href=\"\u002F2012\u002F10\u002Fa-secure-home-gateway-on-raspberry-pi\u002F\">Dynamic DNS\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>Part two - \u003Ca href=\"\u002F2012\u002F10\u002Fa-secure-home-gateway-on-raspberry-pi_14\u002F\">nginx on the Raspberry Pi\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>Part three - \u003Ca href=\"\u002F2012\u002F10\u002Fa-secure-home-gateway-on-raspberry-pi_3759\u002F\">free HTTPS to the rescue\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>\u003Cem>Objective: You want to access the devices inside from outside over the internet, securely\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>So far we used all of the devices above, except for the Popcorn Hour. This device offers, amongst other things, a torrent client over the web. If you go to \u003Ca href=\"http:\u002F\u002F192.168.1.133:8077\">http:\u002F\u002F192.168.1.133:8077\u003C\u002Fa>, or whatever IP your popcorn hour has, you'll get redirected to \u003Ca href=\"http:\u002F\u002F192.168.1.133:8077\u002Ftransmission\u002Fweb\">http:\u002F\u002F192.168.1.133:8077\u002Ftransmission\u002Fweb\u003C\u002Fa>, and you will see the Transmission Web UI. But that's only accessible over the internal network. It'd be nice if we could control our torrents over the web. (Torrents are great for downloading large files like open source linux distro's!).\u003C\u002Fp>\n\u003Cp>So in our nginx configuration file, we add a location directive:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>server {\nserver_name home.waleson.com;\nlisten 443 ssl;\nerror_log \u002Fvar\u002Flog\u002Fnginx\u002Fhome.error;\naccess_log \u002Fvar\u002Flog\u002Fnginx\u002Fhome.access;\nssl on;\nssl_certificate \u002Fusr\u002Flocal\u002Fnginx\u002Fconf\u002Fhome.waleson.com.crt;\nssl_certificate_key \u002Fusr\u002Flocal\u002Fnginx\u002Fconf\u002Fhome.waleson.com.key;\nroot \u002Fsrv\u002Fwww;\nindex index.html \u002Findex.html;\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cblockquote>\n\u003Cp>location \u002Ftransmission {\nproxy_pass \u003Ca href=\"http:\u002F\u002F192.168.1.133:8077\">http:\u002F\u002F192.168.1.133:8077\u003C\u002Fa>;\n}\n}\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Now restart nginx:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>\u002Fetc\u002Finit.d\u002Fnginx restart\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>And voila, we can access the transmission interface securely over the web from \u003Ca href=\"https:\u002F\u002Fhome.waleson.com\u002Ftransmission\u002Fweb\">https:\u002F\u002Fhome.waleson.com\u002Ftransmission\u002Fweb\u003C\u002Fa>. Great!\u003C\u002Fp>\n\u003Cp>I said securely, but it's not really. No one can eavesdrop on the connection itself, but anyone will be able to access our torrent server! Not good, not good!\u003C\u002Fp>\n\u003Cp>We need to password protect everything under \u002Ftransmission.\u003C\u002Fp>\n\u003Cp>To do that, we add two lines to the location directive:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>server {\n....\nlocation \u002Ftransmission {\nauth_basic            &quot;Are you l33t enough to torrent?&quot;;\nauth_basic_user_file  htpasswd;\nproxy_pass \u003Ca href=\"http:\u002F\u002F192.168.1.133:8077\">http:\u002F\u002F192.168.1.133:8077\u003C\u002Fa>;\n}\n}\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>The auth_basic_user_file is a list of usernames and crypted passwords. It is important to realize that the path is relative to the main nginx.conf file in \u002Fetc\u002Fnginx.\u003C\u002Fp>\n\u003Cp>You can easily create a login entry from bash like so:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>printf &quot;USER:$(openssl passwd -crypt PASSWORD)\\n&quot; &gt;&gt; \u002Fetc\u002Fnginx\u002Fhtpasswd\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>To see what this does, run\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>printf &quot;USER:$(openssl passwd -crypt PASSWORD)\\n&quot;\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>to display the output in the terminal itself. It will be:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>USER:CRYPTEDPASS\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Instead of displaying it directly, we want to append that line to a file, so we use &gt;&gt; \u002Fetc\u002Fnginx\u002Fhtpasswd to append the line to the \u002Fetc\u002Fnginx\u002Fhtpasswd file. If it does not exist, it will be created.\u003C\u002Fp>\n\u003Cp>Restart nginx, and now when you go to \u003Ca href=\"https:\u002F\u002Fhome.waleson.com\u002Ftransmission\u002Fweb\">https:\u002F\u002Fhome.waleson.com\u002Ftransmission\u002Fweb\u003C\u002Fa>, you'll be prompted for a password.\u003C\u002Fp>\n\u003Cp>We're not done yet.\u003C\u002Fp>\n\u003Cp>Torrenting is fun, but what about accessing the router settings? As said earlier, this is something that would be cool to do, but you need security. We have https now, so if we work with passwords, they can't be eavesdropped. Let's make it so.\u003C\u002Fp>\n\u003Cp>We could simply add another location like this:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>server {\n....\nlocation \u002Frouter {\nauth_basic            &quot;Are you l33t enough to access the router?&quot;;\nauth_basic_user_file  htpasswd;\nproxy_pass \u003Ca href=\"http:\u002F\u002F192.168.1.1\">http:\u002F\u002F192.168.1.1\u003C\u002Fa>;\n}\n}\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>But if you try this, you will get a 404. The request you made will be sent directly to the router. However, the router's web server has no idea what \u002Frouter means. The admin interface is available under \u002F, not under \u002Frouter\u002F. So instead, we'll have to use a location like this (notice the trailing slashes after \u002Frouter and after the ip):\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>server {\n....\nlocation \u002Frouter\u002F {\nauth_basic            &quot;Are you l33t enough to access the router?&quot;;\nauth_basic_user_file  htpasswd;\nproxy_pass \u003Ca href=\"http:\u002F\u002F192.168.1.1\u002F\">http:\u002F\u002F192.168.1.1\u002F\u003C\u002Fa>;\n}\n}\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>This will strip the \u002Frouter bit from all of the requests.\u003C\u002Fp>\n\u003Cp>Another problem arises, unless you've been careless. Your router's admin interface will prompt you for a password, but nginx has already prompted you for a password. You can only specify one username\u002Fpassword for the entire connection though. If you chose the exact same username\u002Fpassword combination, nginx will probably pass the credentials along with the requests. This could be what you want, but the problem is that it is an implicit contract, which makes it hard to debug when things go awry. Furthermore, I'm not sure that the basic auth attributes aren't stripped from the request by nginx. Fortunately, we have two options to make this work anyway.\u003C\u002Fp>\n\u003Col>\n\u003Cli>No nginx authentication for \u002Frouter\u003C\u002Fli>\n\u003Cli>Let nginx fill in the router credentials for you\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>If we omit the auth_basic settings for the \u002Frouter\u002F location, we are prompted for credentials by the router. It has security so that's all good. Unfortunately, we have to use remember multiple passwords within our nice https portal.\u003C\u002Fp>\n\u003Cp>I chose the second option, by putting the router's credentials in the nginx directive:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>server {\n....\nlocation \u002Frouter\u002F {\nauth_basic            &quot;Are you l33t enough to access the router?&quot;;\nauth_basic_user_file  htpasswd;\nproxy_pass \u003Ca href=\"http:\u002F\u002F192.168.1.1\u002F\">http:\u002F\u002F192.168.1.1\u002F\u003C\u002Fa>;\nproxy_set_header Authorization &quot;Basic XXXXX&quot;;\n}\n}\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Of course you shouldn't put XXXXX there, you should base64 encode the string &quot;USER:PASS&quot; and put it there. Something like this:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>jt@augustine:~$ python\nPython 2.7.3 (default, Aug  1 2012, 05:14:39)\n[GCC 4.6.3] on linux2\nType &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.\n&gt;&gt;&gt; import base64\n&gt;&gt;&gt; base64.b64encode(&quot;USER:PASS&quot;)\n'XXXXX'\n&gt;&gt;&gt;\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Put that XXXXX value in the nginx proxy_set_header and you're all set!\u003C\u002Fp>\n\u003Cp>So there you have it, I can now safely manage my home devices from over the internet! Thank you for reading, and please be thankful for the RaspberryPi foundation and all of the open source packages I used.\u003C\u002Fp>\n",[],{"title":17,"path":18},"WTF Google","\u002F2012\u002F12\u002Fwtf-google\u002F",{"title":20,"path":21},"A secure home gateway on the Raspberry Pi in four parts. Part three, free HTTPS to the rescue","\u002F2012\u002F10\u002Fa-secure-home-gateway-on-raspberry-pi_3759\u002F",[23,28,33,36,40,43,46,50],{"title":24,"path":25,"note":26,"series":27},"Mapping out Dark Code","\u002F2026\u002F03\u002Fmapping-out-dark-code\u002F","2026",false,{"title":29,"path":30,"note":31,"series":32},"The software that I love","\u002F2022\u002F10\u002Fthe-software-that-i-love\u002F","Series · 36 posts",true,{"title":34,"path":35,"note":26,"series":27},"Navigating the Fog of War: Age of Empires, AI Agents, and the Rise of Dark Code","\u002F2026\u002F05\u002Fnavigating-fog-of-war-age-of-empires-ai\u002F",{"title":37,"path":38,"note":39,"series":27},"The Future of Programming Systems - four thoughts","\u002F2024\u002F09\u002Fthe-future-of-programming-systems-four\u002F","2024",{"title":41,"path":42,"note":39,"series":27},"Always Optimize the Feedback Loop","\u002F2024\u002F07\u002Falways-optimize-feedback-loop\u002F",{"title":44,"path":45,"note":39,"series":27},"\"Security Is Our Top Priority\" is BS","\u002F2024\u002F07\u002Fsecurity-is-our-top-priority-is-bs\u002F",{"title":47,"path":48,"note":49,"series":27},"10x teams","\u002F2025\u002F02\u002F10x-teams\u002F","2025",{"title":51,"path":52,"note":49,"series":27},"Hiring, from the Other Side","\u002F2025\u002F10\u002Fhiring-from-other-side\u002F",1792876809144]