3 releases

0.1.2 Jul 4, 2020
0.1.1 Jul 4, 2020
0.1.0 Jul 3, 2020

#432 in HTTP client

MIT license

23KB
175 lines

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

Dependencies

~24–37MB
~689K SLoC