https_demo 0.1.2

https demo website in Rust
https_demo-0.1.2 is not a library.

HTTPS Demo

Demonstrates how to build https website(s) in Rust.

Why this demo?

It took good amount of time to complete my first https website; hence, documenting those learnings!.

Hope, it may help others too!!.

Learnings

Learned to use:

  • tls in code.
  • TLS certificate from Letsencrypt.
  • nginx as reverse proxy on multiple https webservers.

Steps in making a secured website

Step 1: Enabled tls support

  • Unsecured code looked like:
    let ip_addr = CONFIG.ip_address.as_ref().unwrap();  
    let socket_addr: SocketAddr = ip_addr.as_str().parse().unwrap();  
    warp::serve(routes)  
        .run(socket_addr)  
        .await;  
  • added tls code.
    let ip_addr = CONFIG.ip_address.as_ref().unwrap();  
    let cert_path = CONFIG.cert_path.as_ref().unwrap();  
    let key_path = CONFIG.key_path.as_ref().unwrap();  
    let socket_addr: SocketAddr = ip_addr.as_str().parse().unwrap();  
    warp::serve(routes)  
        .tls()  
        .cert_path(cert_path)  
        .key_path(key_path)  
        .run(socket_addr)  
        .await;  
  • For local testing, used a sample certificate found in warp framework example.

  • Ran the server in development machine.

  • Tested it in the browser with url: https​://localhost:3010.

  • Ensured it was working.

Step 2: On the Hosting machine, got a tls certificate

  • On the hosting machine (DigitalOcean in my case),
    a) ensured certbot was installed.
    b) ensured port 80 or 443 were available; those ports were not in use by other programs such as web servers, nginx, or apache.
    c) UFW (Uncomplicated Fire Wall) was disabled ( $ sudo ufw disable ).
    d) iptable entries, that were used for port forwarding to few http websites, were deleted.

  • ran the following command successfully.
    $ sudo certbot certonly --standalone -d example.com

  • tried again for multiple domains.
    $ sudo certbot certonly --standalone -d example.com -d www.example.com OR $ sudo certbot certonly --standalone -d example.com,www.example.com

  • tried to add more domains after obtaining certificates.
    $ sudo certbot certonly --expand -d example.com,www.example.com,new1.example.com,new2.example.com
    It showed two options:

    1. Spin up a temporary webserver (standalone)
    2. Place files in webroot directory (webroot)
      Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1 <-- selected option 1.
  • On success, it showed a `Congratulations!' message and place where certificates were stored.

  • Certificates were stored at /etc/letsencrypt/live/example.com/.

  • Checked the added certificates using following command.
    $ sudo certbot certificates

  • It showed certificate name, domains, certificate path, private key path.

  • For historical reasons, those certificate-containing-directories were created with permissions of 0700 meaning that certificates were accessible only to servers that ran as the root user.

  • Fixed this using command: $ sudo chmod 0755 /etc/letsencrypt/{live,archive}.

  • It was also needed to use chgrp and chmod 0640 to allow the server to read /etc/letsencrypt/live/$domain/privkey.pem. Please note, actual certificates and private keys were in archive folder; live folder contained only links to those files. Hence, applied chmod and chgrp command on archive folder.

Step 3: Deployed Website in several scenarios in an trial and error attempts

Scenario 1: Deployed the website on port 443

  • Made necessary configuration changes in Settings.toml file.
    1. ipaddress was changed from 127.0.0.1:3010 to 0.0.0.0:443.
    2. checked ufw status to ensure port 443 was allowed (using $ sudo ufw status).
    3. ensured Certificate Path and Key path were pointing to letsencrypt folder.
  • Ran the website on command line ( $ ./example ).
  • Checked in the browser with url like: https​://165.1.1.100 ; where 165.1.1.100 was the IP address of the hosting machine.
  • Updated /etc/hosts file with an entry of 127.0.0.1 example.com.
  • Checked the browser with url: https​://example.com.

Scenario 2: Deployed the website on port 3010

  • Made necessary configuration changes in Settings.toml file.
    1. ipaddress was changed from 127.0.0.1:3010 to 0.0.0.0:3010.
    2. added a rule in ufw to allow port 3010 ( $ sudo ufw allow 3010 ).
    3. ensured Certificate Path and Key path was pointing to letsencrypt folder.
  • Ran the website on command line ( $ ./example ).
  • To run it as a service, referred instructions in https_demo.service file.
  • Checked the browser with url: https​://165.1.1.100:3010.
  • Updated or ensured /etc/hosts file with an entry of 127.0.0.1 example.com.
  • Checked the browser with url: https​://example.com:3010.
  • To avoid port number in the url, port forwarding rules were added into iptables; commands were:
    a) $ sudo sysctl net.ipv4.conf.ens3.forwarding=1
    note: network interface ens3 was identified through $ sudo ifconfig.
    b) $ sudo iptables -A PREROUTING -t nat -i ens3 -p tcp --dport 443 -j REDIRECT --to-ports 3010
    c) $ sudo iptables -A FORWARD -t filter -p tcp -d 165.1.1.10 --dport 3010 -j ACCEPT
    d) Checked whether updates were done using:
    $ sudo iptables -t nat -L PREROUTING -n -v --line-numbers
    $ sudo iptables -t filter -L FORWARD -n -v --line-numbers
    e) in case of errors, noted down the row number from above commands and used it in:
    $ sudo iptables -t nat -D PREROUTING <line-number-here> for deleting a row in nat table
    $ sudo iptables -t filter -D FORWARD <line-number-here> for deleting a row in filter table
    Note: -A is for Add, -t for table, -p for protocol, -i for interface, -L for Listing, -D for Delete.
  • Checked the browser with url: https​://example.com (note: no port number this time).

Scenario 3: Deployed multiple websites

  • Above two scenarios worked for single website.
  • To run multiple websites on the same machine, a reverse-proxy server (also known as Gateways) was required.
  • Though a Rust tool on reverse-proxy, for http, was coded based on Hyper example Gateways, it could not be used for https. So, nginx server was used for reverse-proxying.
  • installed nginx server on the hosting machine.
  • tested it was working.
  • referred nginx configuration steps in https-demo.eastgate.in file. It was understood that a separate configuration file was required for each website.

Demo

Demo runs here.

License

MIT