Raspberry Pi Reverse Proxy with NGNIX and Letsencrypt SSL Encryption

One IP address and many or sometimes too may websites hosted on your environment comes with the problem “How to uses standard SSL / HTTPs or HTTP for all of these instead of custom TCP Ports?”. A Raspberry Pi (B3+) in my case Reverse Proxy provide excellent solution to the problem . It is easy to manege Secured by Lets encrypt SSL and energy efficient.

To begin with lets just update the Raspbian to the latest version .

sudo apt update
sudo apt upgrade

Next step is install NGINX on Pi and verify the installed version

sudo apt install nginx
pi@raspberrypi:~ $ sudo nginx -v
nginx version: nginx/1.14.2

Install the certbot for NGINX

sudo apt install python-certbot-nginx

Before proceeding to next step please make sure the raspberry pi is running on static IP and your firewall or router is forwarding the ports TCP/80 and TCP/443 to that IP. Assuming that the domain which will be proxied is already setup to the IP address of your router /firewall. In case of dynamic DNS please refer to the previous post https://www.affan.info/google-domain-ddns-raspberry-pi-or-linux-systems/. Certbot need bot port 80 and 443 to be redirected to the NGINX web server . Once this is done move to next step creation of SSL certificate for the domain.

sudo certbot --nginx --domain demo2.affan.info

Follow the instructions on the console and create the certificate. Next step is to create a NGINX configuration for your website and attach the SSL certificate generated above with it.Verify the certificates created.

pi@raspberrypi:~$ sudo ls /etc/letsencrypt/live/demo1.affan.info/
cert.pem  chain.pem  fullchain.pem  privkey.pem  README

Create a configuration file for NGINX in sites-available directory .

sudo vi /etc/nginx/sites-available/demo1.affan.info.conf

Create the following configuration in the above file and assign the ssl_certificate and ssl_certificate_key parameters. Set the internal IP address for the web server where website is hosted.

server {
    listen 80;
    listen 443 ssl;
    server_name demo1;
    index index.php index.html index.html; #Depend on your Webserver

    #ssl on;
    ssl_certificate /etc/letsencrypt/live/demo1/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/demo1/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    location / {
        proxy_set_header Host $http_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-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://10.10.0.11;               # Internal IP of web server
    }
}

Save the config file and create the link in Sites-enabled directory for NGINX.

sudo ln -s /etc/nginx/sites-available/demo1.affan.info.conf /etc/nginx/sites-enabled/demo1.affan.info.conf

Test NGINX Configuration and Reload id test is ok

pi@raspberrypi:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
pi@raspberrypi:~$ sudo nginx -s reload

Check your website form WAN to make sure everything works. I have run Raspberry-pi B3+ using Ethernet connection to host 5 Websites including a nextcloud instance and depending on internet connection it works fine.

Arduino Water Tank Monitor

Under ground Water-tank or Well level monitor can be a challenge in summer times . I needed a solution in case a refill tanker is needed my IoT environment should alert in time.

Have already Arduino base system running different sensors. Main challenge was the location of water tank which is almost 30 meters away from my current setup. tried to look up the cable maximum length Arduino can support. Using the DC Cable Sizing Tool I calculated that 20 AWG wire will work covering the required distance of 30 meters. (To calculate and learn about the resistance of wires this link can be useful ) On voltmeter 4.98 Volts across the 30 meter coil of the normal 2 pair telephone wire (22 AWG). SR-04 works between 5 to 3.5 Volts and is perfect for this scenario. It transmit Ultrasonic waves and receives back the echo to calculate the distance.

Parts

Arduino UNO1
JSN-SR04 Ultrasonic Water Proof Sensor1
220 Ohm Resistor4
WiresAs needed
Parts Used

Schematic

Schematics

After installation of wires hooked up Arduino with A raspberry pi to get serial Data if needed to re calibrate Water tank depth. This also help to Polt the data using Python.

Code

int Echo = 10;  
int Trigger = 9;
long TimeSpan, Result;  
int depth=200; //define depth of tank in Result
int OneFourth = 4; 
int TwoFourth = 5;
int ThirdFourth = 6;
int FourFourth = 7;

void setup() {

Serial.begin (9600);
pinMode(Trigger, OUTPUT); //Trigger Pin
pinMode(OneFourth, OUTPUT);
pinMode(TwoFourth, OUTPUT);
pinMode(ThirdFourth, OUTPUT);
pinMode(FourFourth, OUTPUT);
pinMode(Echo, INPUT);  //Echo Pin
}

void loop()
{
//Trigger the Sound Pulse
digitalWrite(Trigger, HIGH);
delayMicroseconds(20);

digitalWrite(Trigger, LOW);

TimeSpan = pulseIn(Echo, HIGH);
delay(300);
// The speed of sound is 29.1 microsecond per centimeter. so resulting distance in Centimeters would be
Result = (TimeSpan/2) / 29.1;

// Print Depth to serial port
Serial.print(Result);
Serial.println();

if (Result >= (3*depth/4)) {
    digitalWrite(OneFourth, HIGH);
    digitalWrite(TwoFourth, HIGH);
    digitalWrite(ThirdFourth, HIGH);
    digitalWrite(FourFourth, HIGH);
  } 
else if(Result >= (2*depth/4)){
    digitalWrite(OneFourth, LOW);
    digitalWrite(TwoFourth, LOW);
    digitalWrite(ThirdFourth, HIGH);
    digitalWrite(FourFourth, HIGH);
  }
else if(Result >= (1*depth/4)){
    digitalWrite(OneFourth, LOW);
    digitalWrite(TwoFourth, LOW);
    digitalWrite(ThirdFourth, LOW);
    digitalWrite(FourFourth, HIGH);
  }
else {
    digitalWrite(OneFourth, LOW);
    digitalWrite(TwoFourth, LOW);
    digitalWrite(ThirdFourth, LOW);
    digitalWrite(FourFourth, LOW);
  }

}

above code simply divide the tank in 4 fractions and lights up LED as water level drops.

Microsoft Exchange Services Auto-start

Sometime after a reboot you can notice all of the Microsoft Exchange Services do not started automatically . But if you go to server manager or services and start the pending services they start without fail. Easy way to do it after Microsoft Exchange 2016 reboot is just run the following script.

Get-Service *Exchange* | Start-Service

But you don’t want to start the services which are set to Start Manual or get a lot or warning service already started.. so lets add some steps to the above mentioned .

Get-Service *Exchange* | Where-Object {$_.Status -eq "Stopped" -and $_.StartType -eq "Automatic"} | Start-Service

Above line will check all Microsoft Exchange Services and check stopped services with startup type set to automatic . Next it send the output to Start-Service Cmdlet.

Forgot Domain Admin Password ?

Forgot Domain Administrator Password ? Chances are you will end up finding some expensive tool or some malware. there is a simple and free way to do it .

Requirement:

  • Physical Access to Server
  • Windows Server Installation Media
  • Windows Server 2012 R2 or newer

In our Lab here we will be using Windows Server 2016 Std. This Method will work on Windows Server 2012 R2 and Newer versions also.

Boot server from Windows Server 2016 installation disk. Once reached on setup screen press shift+F10. A command prompt window will open .

Boot Computer from DVD
Press Shift + F10 to Open CMD.exe

We need to replace utilman.exe with cmd.exe in %systemdrive%\windows\system32 folder of installed operation system. on Windows Server 2012 and newer it can be found in C:\ . For some older versions this drive letter may be D:\ or other please verify before proceeding.

move c:\Windows\System32\utilman.exe c:\Windows\System32\utilman.exe.bak
copy c:\Windows\System32\cmd.exe c:\Windows\System32\utilman.exe
Copy the CMD.exe to utilman.exe

Next step is restart your server and let it boot normally .

On the logon screen press Ctrl + Alt + Del and click the accessibility icon as shown in figure . A command prompt will appear .

Click on the Icon

run the command net user to reset the administrator password. Enter your new password.

net user administrator * 
Set New Administrator Password

Close the command prompt and logon with newly created password. Don’t forget to restore original utilman.exe file after logon from c:\Windows\System32\utilman.exe.bak

Remember “There is no Security without physical Security.

Move Process from disconnected SSH session

GNU screen or tmux are great utilities but some times one of your ssh connection is disconnected and process running there vanishes to background on the same pts . My computer running Windows 10 was rebooted due to great windows update active hours settings and there was some apt thing running stopped on some dialog waiting for input.

After some struggle I found about reptyr and that thing saved my day . Just download from https://github.com/nelhage/reptyr .

wget  https://github.com/nelhage/reptyr/archive/reptyr-0.7.0.tar.gz
tar -xzvf reptyr-0.7.0.tar.gz
cd reptyr-reptyr-0.7.0/
make
make install

With minimal Debian web server install above commands installed the reptyr on my machine. Next is few easy steps to get the process moved to new shell session

ps ax | grep myprocess
reptyr PID
......

Get the PID and use this with reptyr command as above . Process for disconnected session will appear from where it was stopped.

Dynamic DNS Raspberry Pi or Linux Systems (domains.google)

Google domains provide excellent Dynamic DNS services free with the hosting for IPv4 and IPv6. In case you have a small web service hosted using dynamic dns this tool can be very helpful for setting up low cost hosting in few minutes. Most of the common Broadband routers these days support on TZO or Dyn.com which are paid services of dyn.com. Create the port forwarding for your broadband or DSL routers to your LAN device IP and the follow the steps.

pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt insatll ddclient

after successful installation of ddclient edit the configuration file at /etc/ddclient.conf in your favorite editor

# Configuration file for ddclient generated by debconf
# /etc/ddclient.conf
ssl=yes
#protocol=dyndns2
protocol=googledomains
use=web
server=domains.google.com
login=googledomaindyndnslogin
password='autogeneratedpasswordformgoogle'
www.affan.info
daemon=100

Protocol is used as

protocol=dyndns2
for other dynamic dns servers but for google
protocol=googledomains
works not the first one. its important to set option
use=web
if this option is not set the ddclient will take the local interface ip instead of the actual IP address of your broadband WAN interface.

Raspberry Pi3 

Once configuration is done save the file and restart the client .

pi@raspberrypi:~ $ sudo service ddclient restart
. To verify the setup and ip run the following command
pi@raspberrypi:~ $ sudo ddclient -query
. Match the output ip with your google domain console.

Empowering the Home Hypervisor Server with VirtualBox

As an IT enthusiast one now a days one must keep some test infrastructure to test and play the IT stuff. Running a virtual machine normally is the easiest way to do this but it have some limitations if it is to be done in a cost effective way. either you have to run a pro versions of Microsoft Windows 8+ on your system or buy some thing from vmware. A good alternative is open source VirtualBox which is limited in some features related to remote management. phpVirtualBox give a nice power to VirtualBox making it possible to run headless Virtual Machines and manage those remotely from any where just using a web browser.
Here is the simple how-to the way I achieved this in my home network making it possible to run all my guest vms which can be managed from any where from a web browser.
Installing phpVirtualBox:
Install VirtualBox and Add-on tools on your windows machine as normal.After the successful installation of VirtualBox we need to install service required to manage the auto start the virtual machine on time of system reboot or shutdown.
Download and install open source sotware VBoxVmService form VboxVmService . Install the service as described .
Edit the VBoxVmService.ini file located in the installation folder of VBoxVmService i.e. c:\vms with basic required settings for the VirtualBox and your headless VM as below

[Settings]
VBOX_USER_HOME=C:\Users\MyUser\.VirtualBox
RunWebService=yes
PauseShutdown=5000
[Vm0]
VmName=MyFirstVM
ShutdownMethod=savestate
AutoStart=yes

Save the VBoxVmService.ini and restart the computer.
Install IIS and PHP on your machine using Microsoft Web Platform Installer.
Download phpVirtualBox from the project website phpVirtualBox. Extract the phpVirtualBox to an appropriate location and in IIS Manager add a virtual directory pointing to phpVirtualBox directory location . Add Basic and Windows Authentication Methods in IIS features if not installed before as this will be the security measure being used which will be discussed later in this article.
Go to phpVirtualBox directory and save config.php-sample as “config.php” Edit config.php in any text editor and check for the following values.

/* SOAP URL of vboxwebsrv (not phpVirtualBox's URL) */
var $location = 'http://127.0.0.1:18083/';
/* Default language. See languages folder for more language options.
* Can also be changed in File -> Preferences -> Language in
* phpVirtualBox.
*/
var $language = 'en';
/* Set the standard VRDE Port Number / Range, e.g. 1010-1020 or 1027 */
var $vrdeports = '9000-9100';
// Disable authentication
var $noAuth = true;

Note highlighted in line 14 we are disabling the php authentication function as this will be taken care by IIS , in most cases this is the only line you need to change in this file to make this running in windows environment.
At this stage you should be able to view the phpVirtualBox Page by browsing i.e. http://localhost/phpVirtualBox

Securing the Web Interface:
now lets move on and secure the newly installed Hypervisor setup . From IIS manager click  to the phpVirtualBox directory and double click the Authentication in IIS Section . Disable anonymous authentication and enable Basic Authentication .

Now go to the phpVirtualBox directory security settings and give read+ write permissions to your windows user on this directory.
Refresh phpVirtualBox link and you will be prompted for user name and password.
if you want to access  this link on internet then its must to run the website on SSL . this can be achieved by creating a self singed certificate in IIS which will be discussed later in some other post.

Connecting NAS to Raspberry Pi

Raspberry Pi is excellent choice to run a low powered fully secure Linux based server . But with the passage of time you experience that the storage on the SD is not enough and some large enough space is required to keep files and backups. USB Hard Drive or a thumb drive could be a work around . Thumb Drive again limit the capacity and USB SATA devices can be hard to manage in terms of physical setup.
Raspberry Pis have 100Mbps ethernet adapter built in which could be used to connect a network drive (NAS) or other file share .
First step is to create the share folder and user on your NAS .  In my case it was WD My Cloud I created user and set a password for that user in NAS.
Mounting the Share to Raspberry Pi
First Login to pi and create a dircetory where we will mount the NAS

pi@raspberrypi:~ $ sudo mkdir /mnt/mycloud

Mount and Test the NAS Share to pi

pi@raspberrypi:~ $ sudo mount -t cifs -o user=pi,passwd=verylongpassword ,rw,file_mode=0777,dir_mode=0777 //192.168.1.10/pi /mnt/mycloud

User  is pi which was created on WD NAS  ie 192.168.1.10 with the password “verylongpassword” but in my case WD My Cloud is not accepting more than 16 characters passwords.
Permanent Mounting
The above command will mount the NAS to pi but it will not be available after reboot. To make this derive permanent we have  to add the settings of the drive in /etc/fstab . Open  fstab with any text editor

pi@raspberrypi:~ $ sudo nano /etc/fstab

 
You will see the list of entries add the last lines as example

roc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that

Enter the Line in end of file as highlighted

roc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
#Mounting the NAS
//192.168.1.10/pi /mnt/mycloud cifs _netdev,user=pi,passwd=verylongpassword,rw,file_mode=0777,dir_mode=0777,iocharset=utf8,comment=systemd.automount 0 0

Hit Ctrl+X and save .
Reboot your Raspbery pi and after login run df -h to see your NAS is mounted on /mnt/mycloud

pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 15G 5.5G 8.6G 39% /
devtmpfs 427M 0 427M 0% /dev
tmpfs 432M 0 432M 0% /dev/shm
tmpfs 432M 6.2M 425M 2% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 432M 0 432M 0% /sys/fs/cgroup
//192.168.1.10/pi 2.7T 896G 1.9T 33% /mnt/mycloud
/dev/mmcblk0p1 63M 21M 43M 34% /boot
tmpfs 87M 0 87M 0% /run/user/1000

Network Drive Bench Mark
Running a simple benchmark on Network drive shows fair Read and Write Speed over 100Mbps Pi Ethernet . First Highlighted line is for Write and Last one is Read Test.

pi@raspberrypi:/mnt/mycloud $ ./diskbench.sh
dd if=/dev/zero of=test.tst bs=4096 count=100000
100000+0 records in
100000+0 records out
409600000 bytes (410 MB) copied, 34.855 s, 11.8 MB/s
dd if=test.tst of=/dev/null bs=4096 count=100000
100000+0 records in
100000+0 records out
409600000 bytes (410 MB) copied, 36.612 s, 11.2 MB/s