Overview

This post is aiming to design and implement a secure web service. The server systems are using debian based system.

Network and Service Design

The firewall of cloud server will only expose two ports 80 and 443 which works for http and https web services.

Creating a secure TCP tunnel for connecting all the servers, in one virtual internal network, same IP range. Using Nginx as proxy and web service on all servers.

details

The cloud server Nginx is used as a layer 7 reverse proxy to local web server or servers to expose web service securely.

Network Setup

Cloud server

Enable firewall on the cloud, based on different provider. Add http and https service to the allow list.

Setup up the secure TCP tunnel. Configure the IP address 172.26.0.9 at /etc/netplan/01-netcfg.yaml

root@Web:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 56:00:01:50:40:b8 brd ff:ff:ff:ff:ff:ff
    inet 207.246.115.80/23 brd 207.246.115.255 scope global dynamic ens3
       valid_lft 81340sec preferred_lft 81340sec
    inet6 2001:19f0:9002:19e5:5400:1ff:fe50:40b8/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591817sec preferred_lft 604617sec
    inet6 fe80::5400:1ff:fe50:40b8/64 scope link 
       valid_lft forever preferred_lft forever
3: tcp_network: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1200 qdisc fq_codel state UNKNOWN group default qlen 1000
    link/ether 12:fd:c0:ce:22:d2 brd ff:ff:ff:ff:ff:ff
    inet 172.26.0.9/16 brd 172.26.255.255 scope global tcp_network
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:bb:ac:2b:4b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

Generate ssh key for login with ssh-keygen

Copy key to the server: ssh-copy-id -i .ssh/id_rsa.pub [email protected]

Disable password login with editing /etc/ssh/sshd_config

PasswordAuthentication no

Local server

Setup up the secure TCP tunnel. Configure the IP address 172.26.0.6 same as the cloud.

Testing connection with cloud server.

tom@local-server:~# ping 172.26.0.9
PING 172.26.0.9 (172.26.0.9) 56(84) bytes of data.
64 bytes from 172.26.0.9: icmp_seq=1 ttl=64 time=1798 ms
64 bytes from 172.26.0.9: icmp_seq=2 ttl=64 time=728 ms
64 bytes from 172.26.0.9: icmp_seq=3 ttl=64 time=282 ms
64 bytes from 172.26.0.9: icmp_seq=4 ttl=64 time=278 ms
64 bytes from 172.26.0.9: icmp_seq=5 ttl=64 time=278 ms
64 bytes from 172.26.0.9: icmp_seq=6 ttl=64 time=162 ms
64 bytes from 172.26.0.9: icmp_seq=7 ttl=64 time=164 ms
64 bytes from 172.26.0.9: icmp_seq=8 ttl=64 time=163 ms
64 bytes from 172.26.0.9: icmp_seq=9 ttl=64 time=164 ms
^C
--- 172.26.0.9 ping statistics ---
11 packets transmitted, 9 received, 18.1818% packet loss, time 120ms
rtt min/avg/max/mdev = 161.755/446.246/1797.787/506.658 ms, pipe 2

Web Service Impletement

Setup Cloud server

Install Nginx and edit /etc/nginx/sites-enabled/default

server {
  listen 80 default_server;
  listen [::]:80 default_server;

#  root /var/www/html;
#  index index.html index.htm index.nginx-debian.html;
#  server_name _;

  # Update domain;
  server_name  itomhu.com *.itomhu.com;

  # Configure all traffic pass to the web service
  location / {
#    try_files $uri $uri/ =404;
    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;

    # Local web server IP address
    proxy_pass              http://172.26.0.6;
  }
}

Reload Nginx:

root@Web:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@Web:~# systemctl reload nginx

Local Web Service

Install Nginx and edit root path of the default configure file. Edit /etc/nginx/sites-enabled/default

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  # Update root path or try default
  root /var/www/html;

  index index.html index.htm index.nginx-debian.html;
  server_name _;

  location / {
    try_files $uri $uri/ =404;
  }
}

Add a test index page:

tom@local-server:~# echo "<h1>Testing</h1>" > /var/www/html/index.html

Reload Nginx:

tom@local-server:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
tom@local-server:~# systemctl reload nginx

Testing

On local server:

tom@local-server:~# curl localhost
<h1>Testing</h1>

On the cloud:

root@Web:~# curl localhost
<h1>Testing</h1>

Now, open the link, “Testing” should showing on the browser.