So finally I bought a Ultimker 3 and it is freaking awesome. I especially like the fact that it has a very nice built in web interface, Cura Connect, allowing you to view the live feed, abort print jobs, reprint, etc.
BUT IT IS USELESS AS IS FOR HOME USERS
The thing is, the web interface does not have any form of authentication, making openning a port on your browser and exposing it extremly dangerous. And why use this in your network if the printer is just steps away?
What I really want is to be able to start a print from anywhere while keeping an eye on it. Ultimaker Cloud allows me to do the first half, but falls short on the second half.
Well, I just have to come up with my own solution.
What you need:
- Router with OpenWrt
- Your own Domain
- Linux Environment, Linux subsystem for windows does NOT work
- Basic computer skills and a bit of patience.
What we are doing (TL;DR):
- Build a custom nginx package on your Linux environment for your router
- Setup dynamic dns on your router
- Create two cnames to point to your router
- Get a free SSL certificate from Let’s Encrypt for those two cnames
- Create two separate nginx reverse proxies, one for your cura connect web page, one for your camera.
- use sub_filter to swap the camera ip address to the cname
- use basic auth for cura connect page
- Expose router ports to the nginx server
Let’s get started
Build Nginx with SSL
on your linux dev box, setup build environment
sudo apt-get install build-essential git-core subversion libssl-dev libncurses5-dev unzip gawk zlib1g-dev libncurses5-dev gcc-multilib flex gettext mercurial
Clone openWrt
git clone https://github.com/openwrt/openwrt.git
cd openwrt
Enter the config menu
make menuconfig
Select the correct target system and subtargets for your router, for example:
Target System : Atheros AR7xxx/AR9xxx
Subtarget : Generic
Target Profile : TP-Link TL-WR1043N/ND
Build OpenWrt
make V=s
This would take a while, about 1 hour.
After this is done, you can build Nginx:
scripts/feeds update
scripts/feeds search nginx
scripts/feeds install nginx
make menuconfig
Go to:
network
Web Servers/proxies
nginx : M
nginx : ENTER
Configuration
Enable SSL module: Y
Build Nginx
time make -j5
Find built ipk pacakge, transfer it to your router and install it
find . -type f -name nginx\*ipk
Setup Dynamic DNS (Use your own preferred dns service if you wish)
Install luci-app-ddns on your router through the UI
Register an account at afraid: https://freedns.afraid.org
Add a free subdomain in the Dynamic DNS page, then copy the direct url link, grab the key behind the update.php?
Create a new entry in your Dynamic DNS page on your router UI
Use afraid-keyauth and paste your key in it. Setup everything else accordingly
After this, create two new CNAME and point them to the domain you just created for your Dnymaic DNS.
Get SSL Certificates from Let’s Encrypt
Install luci-app-acme on your router through the UI
Configure port forwarding in your router to forward both external 443 and 80 to your router’s 443 and 80.
Create a new entry in your ACME certs page in your router, add both cname to it, enable debug and save.
Either restart your browser, or ssh into your router and
/etc/init.d/acme restart
Check your system log for acme, if all is working, disable and remove the port forwarding, note where the cert is stored.
Edit nginx config
First generate a htpasswd file, this is gonna be your login username and password, replace the username in the command
printf "YOURUSERNAME:`openssl passwd -apr1`\n" >> .htpasswd
ssh into your router and with your favorite text editor, open up your /etc/nginx/nginx.config. Use this example file as reference, replace the !!xxx!! with correct value. Example:
user root;
worker_processes 1;
events {
worker_connections 1024;
}
http {
server_names_hash_bucket_size 64;
include mime.types;
sendfile on;
keepalive_timeout 65;
server {
listen 8081;
return 301 https://$host$request_uri;
}
server {
error_log /var/log/nginx/ultimaker_error.log;
access_log /var/log/nginx/ultimaker_access.log;
listen 8443;
server_name !!your-cname!!;
ssl_certificate !!path-to-your-cert!!
ssl_certificate_key !!path-to-your-cert-key!!
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
auth_basic "Restricted Content";
auth_basic_user_file !!/path-to-your-htpasswd!!;
proxy_pass http://!!ultimaker_ip!!:80;
proxy_read_timeout 90;
proxy_redirect http://!!ultimaker_ip!!:80 https://!!your-cname!!;
sub_filter_once off;
sub_filter_types *;
sub_filter 'http://"+r.ip_address+":8080' 'https://!!your-cname2!!';
sub_filter 'http://"+c+":8080' 'https://!!your-cname2!!';
}
}
server {
error_log /var/log/nginx/ultimaker-cam_error.log;
access_log /var/log/nginx/ultimaker-cam_access.log;
listen 8443;
server_name !!your-cname2!!;
ssl_certificate !!path-to-your-cert!!
ssl_certificate_key !!path-to-your-cert-key!!
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://!!ultimaker_ip!!:8080;
proxy_read_timeout 90;
proxy_redirect http://!!ultimaker_ip:8080!! https://!!your-cname2!!;
}
}
}
Let me explain it a little bit
server {
listen 8081;
return 301 https://$host$request_uri;
}
This redirects http to https
sub_filter_once off;
sub_filter_types *;
sub_filter 'http://"+r.ip_address+":8080' 'https://!!your-cname2!!';
sub_filter 'http://"+c+":8080' 'https://!!your-cname2!!';
This replaces the video links on your page to the camera cname, your stuff might be a little different, use chrome page inspector to find these urls
auth_basic "Restricted Content";
auth_basic_user_file !!/path-to-your-htpasswd!!;
This adds authentication to your cura connect page
To finish up, setup port forwarding
Forward external 80 to your router’s 8081, Forward external 443 to yur router’s 8443.
Check your work by turning on your Ultimaker and load up your cname with your browser