Continuous Credential Prompt when accessing MIM Password Registration Portal

Recently I was at a customer site, setting up a Microsoft Identity Manager (MIM) 2016 environment, which included the deployment of the Self Service Password Registration and Self Service Password Reset portals. For additional security, I was using Kerberos instead of the default NTLM.

I finished installing the MIM Portal, Service, Password Registration and Password Reset Portals without any issues.

I then proceeded to securing all http endpoints by enabling them for SSL and after that removing the http bindings, so that you could access the MIM Portal, Password Registration and Password Reset Portals only via https. No issues there as well.

By this time I was pretty pleased with myself ūüėČ Everything was going as planned, no issues faced at all. Finally, lady luck was showering me with her blessings.

Having finished the installation and configuration, I proceeded to testing the solution.

The first thing to check was the MIM Portal site. I opened up a web browser and navigated to the Microsoft Identity Manager Portal. When prompted, I logged in with the mimadmin domain account credentials. I was successfully logged in and could access all the parts without any hitch.

Now kids, if you are faint at heart, be very wary of what happens next (hint. this is the time when you cover your eyes with your hands when watching a horror movie).

I then tried accessing the Self Service Password Registration Portal and got prompted for credentials.


I entered the mimadmin account credentials and pressed enter. Just as I thought I had successfully logged in, the credential prompt returned! hmm, that is weird. I was pretty sure I had typed the username and password correctly. Oh well, maybe I didn’t.

I typed the credentials again and pressed enter. Quick as a flash, the credential prompt returned! Uh? What was happening here?{scratching my head} Hmm, I seem to be making a lot of typos today. I carefully entered the username and password again, taking my time this time, to ensure I was entering it correctly. I then pressed enter and waited.

Well, I didn’t have to wait for long since within a second, I got greeted with the¬†Not Authorized screen!


Fascinating. It seems that lady luck had flown away because here indeed was an issue with the Self Service Password Registration Portal! Ok, Mister. Lets have a look at whats causing this kerfuffle!

I opened up the event viewer on the Self Service Password Registration server and went through each of the logged events in the Application and System logs, however I couldn’t find any clue as to why the credentials were not working. I secretly had suspicions that the issue could be due to Kerberos token errors, however I couldn’t find anything in the event logs to substantiate my suspicion. Hmm, the plot was indeed getting thicker!

I next started doing some Google searches, thinking that someone else might have encountered the same issue. Alas, it seemed that I was alone in my woes as the results seemed to be quite thin in regards to any possible solution for my issue.

Finally, I decided to follow my dear ol’ Sherlock’s advice “when you have eliminated the impossible, whatever remains, however improbable, must be the truth”

I went through the whole Self Service Password Registration setup process, checking each and every part of the configuration, to ensure that the values were as expected. After 10 minutes, I was almost done checking and no clues so far ūüė¶

Lastly, I opened IIS Manager and checked all the settings. Nothing here as well. Hey back up a bit. What is this?

The Self Service Password Registration Portal site had its useAppPoolCredentials set to False.


Now, this should be True! Is this what was causing the issue?

I quickly changed the value for useAppPoolCredentials from False to True.


I then opened my web browser again and navigated to the Self Service Password Registration Portal. Once again the familiar credential prompt came up. I entered the same credentials as before and pressed enter.

Woo hoo!! This time around I was successfully logged in.

I sincerely hope that this post helps others who might be encountering the same error.

Have a great day ūüėČ



Ok Google Email me the status of all vms – Part 2

In my last blog, we configured the backend systems necessary for accomplishing the task of asking Google Home “OK Google Email me the status of all vms” and it sending us an email to that effect. If you haven’t finished doing that, please refer back to my last blog¬†and get that done¬†before continuing.

In this blog, we will configure Google Home.

Google Home uses Google Assistant to do all the smarts. You will be amazed at all the tasks that Google Home can do out of the box.

For our purposes, we will be using the platform IF This Then That or IFTTT for short. IFTTT is a very powerful platform as it lets you create actions based on triggers. This combination of triggers and actions is called a recipe.

Ok, lets dig in and create our IFTTT recipe to accomplish our task

1.1 ¬† Go to¬†¬†and create an account (if you don’t already have one)

1.2   Login to IFTTT and click on My Applets menu from the top


1.3   Next, click on New Applet (top right hand corner)

1.4   A new recipe template will be displayed. Click on the blue + this choose a service


1.5 ¬† Under¬†Choose a Service¬†type “Google Assistant”


1.6   In the results Google Assistant will be displayed. Click on it

1.7 ¬† If you haven’t already connected IFTTT with Google Assistant, you will be asked to do so. When prompted, login with the Google account that is associated with your Google Home and then approve IFTTT to access it.


1.8   The next step is to choose a trigger. Click on Say a simple phrase


1.9   Now we will put in the phrases that Google Home should trigger on.



  • What do you want to say? enter “email me the status of all vms
  • What do you want the Assistant to say in response? enter “no worries, I will send you the email right away

All the other sections are optional, however you can fill them if you prefer to do so

Click Create trigger

1.10   You will be returned to the recipe editor. To choose the action service, click on + that


1.11  Under Choose action service, type webhooks. From the results, click on Webhooks


1.12   Then for Choose action click on Make a web request


1.13   Next the Complete action fields screen is shown.


  • URL – paste the webhook url of the runbook that you had copied in the previous blog
  • Method – change this to¬†POST
  • Content Type – change this to¬†application/json


Click Create action

1.13   In the next screen, click Finish



Woo hoo. Everything is now complete. Lets do some testing.

Go to your Google Home and say “email me the status of all vms”. Google Home should reply by saying “no worries. I will send you the email right away”.

I have noticed some delays in receiving the email, however the most I have had to wait for is 5 minutes. If this is unacceptable, in the runbook script, modify the Send-MailMessage command by adding the parameter -Priority High. This sends all emails with high priority, which should make things faster. Also, the runbook is currently running in Azure. Better performance might be achieved by using Hybrid Runbook Workers

To monitor the status of the automation jobs, or to access their logs, in the Azure Automation Account, click on Jobs in the left hand side menu. Clicking on any one of the jobs shown will provide more information about that particular job. This can be helpful during troubleshooting.


There you go. All done. I hope you enjoy this additional task you can now do with your Google Home.

If you don’t own a Google Home yet, you can do the above automation using Google Assistant as well.

Ok Google Email me the status of all vms – Part 1

Technology is evolving at a breathtaking pace. For instance, the phone in your pocket has more grunt than the desktop computers of 10 years ago!

One of the upcoming areas in Computing Science is Artificial Intelligence. What seemed science fiction in the days of Isaac Asimov, when he penned I, Robot seems closer to reality now.

Lately the market is popping up with virtual assistants from the likes of Apple, Amazon and Google. These are “bots” that use Artificial Intelligence to help us with our daily lives, from telling us about the weather, to reminding us about our shopping lists or letting us know when our next train will be arriving. I still remember my first virtual assistant¬†Prody Parrot, which hardly did much when you compare it to Siri, Alexa or Google Assistant.

I decided to test drive one of these virtual assistants, and so purchased a Google Home. First impressions, it is an awesome device with a lot of good things going for it. If only it came with a rechargeable battery instead of a wall charger, it would have been even more awesome. Well maybe in the next version (Google here’s a tip for your next version ūüėČ )

Having played with Google Home for a bit, I decided to look at ways of integrating it with Azure, and I was pleasantly surprised.

In this two-part blog, I will show you how you can use Google Home to send an email with the status of all your Azure virtual machines. This functionality can be extended to stop or start all virtual machines, however I would caution against NOT doing this in your production environment, incase you turn off some machine that is running critical workloads.

In this first blog post, we will setup the backend systems to achieve the tasks and in the next blog post, we will connect it to Google Home.

The diagram below shows how we will achieve what we have set out to do.

Google Home Workflow

Below is a list of tasks that will happen

  1. Google Home will trigger when we say “Ok Google email me the status of all vms”
  2. As Google Home uses Google Assistant, it will pass the request to the IFTTT service
  3. IFTTT will then trigger the webhooks service to call a webhook url attached to an Azure Automation Runbook
  4. A job for the specified runbook will then be queued up in Azure Automation.
  5. The runbook job will then run, and obtain a status of all vms.
  6. The output will be emailed to the designated recipient

Ok, enough talking ūüėČ lets start cracking.

1. Create an Azure AD Service Principal Account

In order to run our Azure Automation runbook, we need to create a security object for it to run under. This security object provides permissions to access the azure resources. For our purposes, we will be using a service principal account.

Assuming you have already installed the Azure PowerShell module, run the following in a PowerShell session to login to Azure

Import-Module AzureRm

Next, to create an Azure AD Application, run the following command

$adApp = New-AzureRmADApplication -DisplayName "DisplayName" -HomePage "HomePage" -IdentifierUris "http://IdentifierUri" -Password "Password"


DisplayName is the display name for your AD Application eg “Google Home Automation”

HomePage is the home page for your application eg http://googlehome (or you can ignore the -HomePage parameter as it is optional)

IdentifierUri is the URI that identifies the application eg http://googleHomeAutomation

Password is the password you will give the service principal account

Now, lets create the service principle for the Azure AD Application

New-AzureRmADServicePrincipal -ApplicationId $adApp.ApplicationId

Next, we will give the service principal account read access to the Azure tenant. If you need something more restrictive, please find the appropriate role from

New-AzureRmRoleAssignment -RoleDefinitionName Reader -ServicePrincipalName $adApp.ApplicationId

Great, the service principal account is now ready. The username for your service principal is actually the ApplicationId suffixed by your Azure AD domain name. To get the Application ID run the following by providing the identifierUri that was supplied when creating it above

Get-AzureRmADApplication -IdentifierUri {identifierUri}

Just to be pedantic, lets check to ensure we can login to Azure using the newly created service principal account and the password. To test, run the following commands (when prompted, supply the username for the service principal account and the password that was set when it was created above)

$cred = Get-Credential 
Login-AzureRmAccount -Credential $cred -ServicePrincipal -TenantId {TenantId}

where Tenantid is your Azure Tenant’s ID

If everything was setup properly, you should now be logged in using the service principal account.

2. Create an Azure Automation Account

Next, we need an Azure Automation account.

2.1   Login to the Azure Portal and then click New


2.2   Then type Automation and click search. From the results click the following.


2.3   In the next screen, click Create

2.4   Next, fill in the appropriate details and click Create


3. Create a SendGrid Account

Unfortunately Azure doesn’t provide relay servers that can be used by scripts to email out. Instead you have to either use EOP (Exchange Online Protection) servers or SendGrid to achieve this. SendGrid is an Email Delivery Service that Azure provides, and you need to create an account to use it. For our purposes, we will use the free tier, which allows the delivery of 2500 emails per month, which is plenty for us.

3.1   In the Azure Portal, click New


3.2   Then search for SendGrid in the marketplace and click on the following result. Next click Create


3.3   In the next screen, for the pricing tier, select the free tier and then fill in the required details and click Create.


4. Configure the Automation Account

Inside the Automation Account, we will be creating a Runbook that will contain our PowerShell script that will do all the work. The script will be using the Service Principal and SendGrid accounts. To ensure we don’t expose their credentials inside the PowerShell script, we will store them in the Automation Account under Credentials, and then access them from inside our PowerShell script.

4.1   Go into the Automation Account that you had created.

4.2   Under Shared Resource click Credentials


4.3    Click on Add a credential and then fill in the details for the Service Principal account. Then click Create


4.4   Repeat step 4.3 above to add the SendGrid account

4.5   Now that the Credentials have been stored, under Process Automation click Runbooks


Then click Add a runbook and in the next screen click Create a new runbook

4.6   Give the runbook an appropriate name. Change the Runbook Type to PowerShell. Click Create


4.7   Once the Runbook has been created, paste the following script inside it, click on Save and then click on Publish

Import-Module Azure
$cred = Get-AutomationPSCredential -Name 'Service Principal account'
$mailerCred = Get-AutomationPSCredential -Name 'SendGrid account'

Login-AzureRmAccount -Credential $cred -ServicePrincipal -TenantID {tenantId}

$outputFile = $env:TEMP+ "\AzureVmStatus.html"
$vmarray = @()

#Get a list of all vms 
Write-Output "Getting a list of all VMs"
$vms = Get-AzureRmVM
$total_vms = $vms.count
Write-Output "Done. VMs Found $total_vms"

$index = 0
# Add info about VM's to the array
foreach ($vm in $vms){ 
 Write-Output "Processing VM $index/$total_vms"
 # Get VM Status
 $vmstatus = Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status

# Add values to the array:
 $vmarray += New-Object PSObject -Property ([ordered]@{
$vmarray | Sort-Object PowerState,OSType -Desc

Write-Output "Converting Output to HTML" 
$vmarray | Sort-Object PowerState,OSType -Desc | ConvertTo-Html | Out-File $outputFile
Write-Output "Converted"

$fromAddr = "senderEmailAddress"
$toAddr = "recipientEmailAddress"
$subject = "Azure VM Status as at " + (Get-Date).toString()
$smtpServer = ""

Write-Output "Sending Email to $toAddr using server $smtpServer"
Send-MailMessage -Credential $mailerCred -From $fromAddr -To $toAddr -Subject $subject -Attachments $outputFile -SmtpServer $smtpServer -UseSsl
Write-Output "Email Sent"


  • ‘Service Principal Account’ and ‘SendGrid Account’ are the names of the credentials that were created in the Automation Account (include the ‘ ‘ around the name)
  • senderEmailAddress is the email address that the email will show it came from. Keep the domain of the email address same as your Azure domain
  • recipientEmailAddress is the email address of the recipient who will receive the list of vms

4.8   Next, we will create a Webhook. A webhook is a special URL that will allow us to execute the above script without logging into the Azure Portal. Treat the webhook URL like a password since whoever possesses the webhook can execute the runbook without needing to provide any credentials.

Open the runbook that was just created and from the top menu click on Webhook


4.9   In the next screen click Create new webhook

4.10  A security message will be displayed informing that once the webhook has been created, the URL will not be shown anywhere in the Azure Portal. IT IS EXTREMELY IMPORTANT THAT YOU COPY THE WEBHOOK URL BEFORE PRESSING THE OK BUTTON.

Enter a name for the webhook and when you want the webhook to expire. Copy the webhook URL and paste it somewhere safe. Then click OK.

Once the webhook has expired, you can’t use it to trigger the runbook, however before it expires, you can change the expiry date. For security reasons, it is recommended that you don’t keep the webhook alive for a long period of time.


Thats it folks! The stage has been set and we have successfully configured the backend systems to handle our task. Give yourselves a big pat on the back.

Follow me to the next blog, where we will use the above with IFTTT, to bring it all together so that when we say “OK Google, email me the status of all vms”, an email is sent out to us with the status of all the vms ūüėČ

I will see you in Part 2 of this blog. Ciao ūüėČ

Building a VPN Solution using OpenVPN Server on a Raspberry Pi – Part 2 Configuring the clients

Now that we have configured the openvpn server, we will continue on to configuring the clients. If you haven’t configured the openvpn server yet, please refer to my previous blog

To connect to the openvpn server, the client needs a ovpn file. This file contains the required certificates and the openvpn servers address. The article at provides the steps required. However I have deviated from the steps listed in that article abit, for the following reasons

  • I am not using comp-lzo, which is used for backwards compatibility
  • I am using AES-256-CBC
  • I am using a more verbose level (verb 3)

Now that the above is out of the way, use the steps below to generate the client configuration file

  1. On the Raspberry Pi, using terminal, elevate your session to root and then change to the easy-rsa keys folder using the following command
   sudo su
   cd /etc/openvpn/easy-rsa/keys

2.     Create a new file with the following lines and save it as Default.txt ( do not forget to replace <your public domain name to openvpn server> with your openvpn public hostname)

   dev tun
   proto udp
   remote <your public domain name to openvpn server> 1194
   resolv-retry infinite
   ns-cert-type server
   key-direction 1
   cipher AES-256-CBC
   verb 3
   mute 20

3.   Download the script from Github using the following command (the actual Github url is The command below is using the raw version of the file)


4.   The script needs some modification to match our openvpn server configuration. Modify the script based on the following

change line 7 from KEY=".3des.key" to KEY=".aes256.key"
change line 21 from echo "Client’s cert found: $NAME$CR" to 
echo "Client’s cert found: $NAME$CRT" 
change line 72 by adding a # in front of the line (so you are commenting out the line)

5. The script will be owned by root. Grant it execute permissions by running the following

  chmod u+rwx

6.  Now execute the script using the following command. You will be asked for the name of an existing client for whom you had generated the keys and certificates for when configuring the openvpn server (for instance client1)


The script checks to ensure the following files exist in the folder /etc/openvpn/easy-rsa/keys


If any of the above files are missing, an error is displayed and the script stops.

However, if everything goes well, the following is displayed

Done! {client1}.ovpn Successfully Created.

and the file {client1}.ovpn is placed in the /etc/openvpn/easy-rsa/keys folder

7. ¬† Thats it folks! The client config file is now ready. Import it into your openvpn client to connect to your openvpn server. Don’t forget the password you had configured for the client when you generated the key because it will be requested everytime you try connecting to the openvpn server.

A good MacOS OpenVPN client is On IOS, you can download the  free OpenVPN Connect app.

Let me know what you think of my blog and enjoy the privacy and benefits of the vpn server ūüôā

Building a VPN Solution using OpenVPN Server on a Raspberry Pi – Part 1 Configuring the Server


Recently I got asked by a friend to recommend a good router/modem that will allow him to vpn into his home network. He was concerned about his internet traffic being eavesdropped on when he connected to a network he didn’t know much about (ah yes, he could just NOT connect to these dodgy networks I hear you say ūüôā )

Well being the good friend that I am, I pointed him to some good routers/modems however it got me thinking. Why not use a Raspberry Pi to accomplish this feat? After a bit of salesmanship, I got my friend convinced that a OpenVPN server running on a ¬†Raspberry Pi was the best solution ūüôā

After placing our order for the Raspberry Pi (and the case, power adapter, sd card etc), I started researching on how I would get OpenVPN installed and configured. A quick google search revealed a lot of articles, so I felt quite confident that this task wasn’t too difficult. Well, lets just say that my opinion changed once I started the configuration! I couldn’t find any ONE blog that told me exactly what had to be done. There was always something missing and I had to do my own research to fill in that gap. And that my friend, is essentially the motivation for this blog, to provide a one stop shop for anyone trying to install/configure a OpenVPN server on a Raspberry Pi.

Below are the list of websites I consulted for my configuration

In this part, I will show you how to install and then configure openvpn on a Raspberry Pi. In the next blog post, I will show you how to configure the clients, so that they can connect to the openvpn server.


Before we begin, the following are required

  1. Raspberry Pi (obviously ūüėÄ )
  2. Raspbian (for those that are not aware, Raspbian is the operating system that runs on Raspberry Pis. Instructions on how to install it can be found at )
  3. a static internal ip address for the Raspberry Pi. This can be easily done by reserving an ip address on your router for the Raspberry Pi
  4. create a port forwarding rule on your router to forward all udp 1194 traffic it receives from the internet to your Raspberry Pi.
  5. an internet routable domain name. If you don’t already own a public DNS hostname, you can use services like¬†¬†to get a free domain.
  6. some means of accessing your Raspberry Pi. Initially you will need a usb keyboard and mouse and a tv screen to access it, however the latest builds of Raspbian include RealVNC server by default, so you can configure and then remotely connect to the Raspberry Pi from another computer.
  7. OpenVPN Server comes with 2 free client connection licenses for testing. If you are going to use it for anything other than testing, please visit to purchase the licenses.

Server Implementation Steps

  1. First and foremost, we need to secure the Raspberry Pi. By default it comes with a username pi and the password for this account is set to raspberry. You can either change the default password by using sudo passwd or create a new account with the same privileges as pi and then lock/delete the pi account. The article at shows how you can create a new account and then lock pi.
  2. Next, start a terminal session and run the following to install openvpn
   sudo apt-get update
   sudo apt-get upgrade
   sudo apt-get install openvpn -y

3.    Open /etc/sysctl.conf using your favorite text editor (I am using nano)

   sudo nano /etc/sysctl.conf

4.     Uncomment (remove the # prefix) the following line and save the changes


5.    Run the following command to make the change persistent over reboots

   sudo sysctl -p

6.    Next, we will setup a Certificate Authority (CA) and generate certificates and                 keys for the OpenVPN server and clients. For the CA, we will use easy-rsa, a PKI  solution that comes bundled with OpenVPN 2.3.4.

In the terminal window, elevate the session to root privileges using the following

  sudo -s

7.   Then copy the easy-rsa folder to a subfolder under the openvpn folder

  cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa

8.   Next, modify the vars file included with easy-rsa (I am using nano to modify the file)

  cd /etc/openvpn/easy-rsa
  nano vars

9.   Since we have copied easy-rsa to a new location, change the following line from

  export EASY_RSA="`pwd`" to  export EASY_RSA="/etc/openvpn/easy-rsa"

10.   Scroll down and change KEY_SIZE to 2048 (if different)

   export KEY_SIZE=2048

11. ¬† Going down a few more lines, you will see the default fields that will be used for the certificates. Change these to the appropriate values so that you don’t have to change it each time a certificate is generated

   # These are the default values for fields
   # which will be placed in the certificate.
   # Don't leave any of these fields blank.
   export KEY_COUNTRY="US"
   export KEY_PROVINCE="CA"
   export KEY_CITY="SanFrancisco"
   export KEY_ORG="Fort-Funston"
   export KEY_EMAIL="me@myhost.mydomain"
   export KEY_OU="MyOrganizationalUnit"

12.   Save the changes and exit the text editor

13.   All the prep work has now been done. Lets start with the certificate generation process. Run the following command to build the vars file

   source ./vars

14.   Next, remove any previously generated keys by running the following command (this will delete all contents of /etc/openvpn/easy-rsa/keys folder)


15. ¬† Create a Certificate Authority by running the following command and filling in the appropriate values. Press enter to accept the default values or “.” to leave them as blank. For Common Name¬†you can enter¬†OpenVPN-CA


(screenshot from

16. ¬† Next, generate a server certificate and key using the following command (¬†For each of the requested fields, either accept the defaults by pressing Enter or leave them blank by entering “.” ¬†Also, note down the following as well

  • Common Name¬†– enter the public DNS record to your server.
  • when asked for “A challenge password []:” enter “.” to leave it blank.
  • when asked for “An optional company name []:” enter “.” to leave it blank.
  • when asked¬†“Sign the certificate (y/n):” enter¬†y
  • when asked¬†“1 out of 1 certificate requests certified, commit? [y/n]” enter y

{servername} refers to a name for your server (you can use your public DNS name)

   ./build-key-server {servername}

(screenshot from

17.   Next, run the following command to generate a certificate for {client1} where client1 is the name of a user who will be able to use openvpn.

For each of the requested fields, either accept the defaults by pressing enter or leave them blank by entering “.” The most important field is the¬†PEM pass phrase. This is the password that the user will enter every time they establish a vpn session.

Also, when requested for

  • A challenge password []:”¬†– leave this field blank by entering “.”
  • An optional company name []:” – leave this field blank by entering “.”

The command to run isc

   ./build-key-pass {client1}

(screenshot from

18.  AES-256-CBC will be used as the key encryption scheme, so firstly, run the following command and check the output to ensure that your version of OpenVPN supports it

   openvpn --show-ciphers

19. ¬† Next, generate an AES 256 key for {client1} using the following command (replace¬†client1 with the name you gave your user above). You will be asked for “Enter pass phrase for {Client1}.key” – for simplicity, you can make this the same as what you had in step 17 above. Enter the same password when asked for¬†PEM pass phrase¬†

   cd keys
   openssl rsa -in {client1}.key -aes256 -out {client1}.aes256.key

(screenshot from

20.   Repeat steps 17 Р19 for any additional users that you want to enable for VPN access

21.   Next, we will generate the Diffie-Hellman keys. Use the following commands to do this (be warned that it can take at least 15 minutes for the dh keys to get generated!)

   cd ..


22. ¬† Ahem, this is turning out to be a long blog. Bear with me, we are not too far away from completing the OpenVPN setup ūüėČ

Since our OpenVPN server will be open to the big bad internet, we need to ensure it is properly secured. To do this, we will be using tls-auth


“The tls-auth directive adds an additional HMAC signature to all SSL/TLS handshake packets for integrity verification. Any UDP packet not bearing the correct HMAC signature can be dropped without further processing. The tls-auth HMAC signature provides an additional level of security above and beyond that provided by SSL/TLS. It can protect against:

  • DoS attacks or port flooding on the OpenVPN UDP port.
  • Port scanning to determine which server UDP ports are in a listening state.
  • Buffer overflow vulnerabilities in the SSL/TLS implementation.
  • SSL/TLS handshake initiations from unauthorized machines (while such handshakes would ultimately fail to authenticate, tls-auth can cut them off at a much earlier point).”

Using tls-auth requires the generation of a shared secret key that is used in addition to the standard RSA certificate/key. Run the following command to generate this (ensure you are in the /etc/openvpn/easy-rsa/keys folder)

  openvpn --genkey --secret keys/ta.key

23.   Next, we will create a customised OpenVPN server configuration file. A sample server.conf file is already present. Use the following commands to copy it to /etc/openvpn folder (ensure you are already in the /etc/openvpn folder)

  cp -v /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz  /etc/openvpn
  gunzip -v /etc/openvpn/server.conf.gz

After unzipping the file, server.conf will be placed in /etc/openvpn

24.   It is good practise to rename server.conf file to your servername. This differentiates it from the standard template file. In my case, I have renamed it to servername.conf. Open the servername.conf file using a text editor (I am using nano)

   nano servername.conf

25.  We will go through the file servername.conf and change the following items. If the items are commented out using a prefix of # or ; then uncomment them

I have read numerous places that the line ;local a.b.c.d needs to be uncommented and a.b.c.d needs to be changed to the OpenVPN server’s ip address. However, when I did that, my OpenVPN server would always error when the Raspberry Pi boots/reboots with the following error

“TCP/UDP: Socket bind failed on local address [AF_INET]{ipaddress}:1194: Cannot assign requested address”

To fix this issue, I left the line ;local a.b.c.d commented out

port 1194
proto udp
dev tun

The key locations need to be updated to the following. These will correspond to the keys that were generated above

ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/{servername}.crt
key /etc/openvpn/easy-rsa/keys/{servername}.key
dh  /etc/openvpn/easy-rsa/keys/dh2048.pem

the following should remain as they are

ifconfig-pool-persist ipp.txt

the following lines push settings to the clients that connect to the vpn. These values override what the client already has

push "route"
push "route {raspberry pi ip address}
push "dhcp-option DNS {your home router's internal ip address}"

the next line makes sure that all of the client’s traffic passes through the OpenVPN server. We will setup the OpenVPN server to handle this traffic via NAT a bit further down in this blog

push "redirect-gateway def1"

Uncomment the following line if you want the connected clients to reach each other. By default, the clients can only reach to the server


It is not recommended, however if you are going to have multiple clients connect to the OpenVPN server using the same certificate/key files or common names then uncomment the following. IT IS HIGHLY RECOMMENDED THAT EACH CLIENT HAVE THEIR OWN CERTIFICATE/KEY and COMMON NAME.


Update the location of the tls-auth key with the following line

tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0

ensure the cryptographic cipher is setup to the following

cipher AES-256-CBC

Next, we need to strip all permissions and privileges from the openvpn process when it runs, so that in case it gets compromised, there is no permission leak. This is done by uncommenting the following lines

user nobody
group nobody

Scroll down a few more lines and check that the following are listed in the config file


Lets enable logging and ensure they are all output to /var/log folder. Change the status log line as below

status /var/log/openvpn-status.log

for the actual log file, you can either enable the log file to get rewritten every time openvpn starts or you can append to the existing log file. I personally prefer log-append. So, based on your selection, uncomment one of the following and change appropriately

log /var/log/openvpn.log
log-append  /var/log/openvpn.log

Lastly, make sure the following lines are present in the config file

verb 3
explicit-exit-notify 1

save the configuration file

26.   Next on the list is configuring NAT on the Raspberry Pi interface that is being used by the openvpn server. For the sake of portability, I am using wlan0 however you can use the ethernet interface (now be careful when you use the ethernet interface, on Raspberry Pi 3, it is not named something simple as eth0 but it is enx{mac-address} where mac-address is the mac-address of the interface)

Use the following line to enable NAT on the wireless interface

iptables -t nat -A POSTROUTING -s -o wlan0 -j MASQUERADE

save the updated rules using the following to make it persistent

iptables-save > /etc/iptables/rules.v4

27. ¬† Let’s test that openvpn is happy with the configuration file. To do this, run the following command

openvpn servername.conf

check the logs at /var/log/openvpn.log to ensure you see something similar to below

Sun Feb 6 20:46:38 2005 OpenVPN 2.0_rc12 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb 5 2005
Sun Feb 6 20:46:38 2005 Diffie-Hellman initialized with 1024 bit key
Sun Feb 6 20:46:38 2005 TLS-Auth MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ]
Sun Feb 6 20:46:38 2005 TUN/TAP device tun1 opened
Sun Feb 6 20:46:38 2005 /sbin/ifconfig tun1 pointopoint mtu 1500
Sun Feb 6 20:46:38 2005 /sbin/route add -net netmask gw
Sun Feb 6 20:46:38 2005 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:23 ET:0 EL:0 AF:3/1 ]
Sun Feb 6 20:46:38 2005 UDPv4 link local (bound): [undef]:1194
Sun Feb 6 20:46:38 2005 UDPv4 link remote: [undef]
Sun Feb 6 20:46:38 2005 MULTI: multi_init called, r=256 v=256
Sun Feb 6 20:46:38 2005 IFCONFIG POOL: base= size=62
Sun Feb 6 20:46:38 2005 IFCONFIG POOL LIST
Sun Feb 6 20:46:38 2005 Initialization Sequence Completed


28.   Now that we have confirmation that the configuration is successful, the only task left is to ensure that openvpn server starts automatically every time Raspberry Pi starts. To do this, open /etc/defaults/openvpn using a text editor and add the following underneath the bunch of lines starting with AUTOSTART


So, essentially, below is what you should see (the text in orange is what was added)

#AUTOSTART="home office"

Woo hoo! Give your self a pat on the back for a job well done! The openvpn server configuration is now complete. I am mindful that this blog has grown to a mammoth size. I will detail the client configuration in the next blog. So off you go, have a break, a refreshing beverage if you must and come back for the client configuration ūüôā

The client configuration settings are found at


Enable true hibernation mode in MacOS

I had meant to have this blog posted a few months back, unfortunately it got stuck on my todo list and never quite made it out, till now.

I decided to go back to a MacBook Pro a few months back, because my Surface Pro 3 was just not capable of running virtual machines. I absolutely love my MacBook Pro 15inch, it runs anything I throw at it, my only gripe is that the memory cannot be upgraded beyond 16GB. I would happily pay more to get 32GB on it.

I had been using a MacBook Pro 13 inch last year, running OS X Mavericks. One of the features I absolutely loved was hibernate to disk. In my view this is much better than sleep mode because my system state is written to disk, instead of being kept in RAM, which needs to be powered on (this is sleep mode). True hibernation (hibernate to disk) is same as the hibernate mode you get with Windows.

To my surprise, when I went to configure hibernate to disk on my new MacBook Pro, my previous steps didn’t work ūüė¶ Ok, I was running MacOS Sierra now, however I expected the process to be the same.

Being the person that rarely gives up (and hibernate to disk was a feature I really really wanted), I started researching on what had happened to it. I managed to find an article from Apple that listed all the supported sleep modes, and oh wait a minute, what is that I see. Aha, Apple calls hibernate to disk Safe sleep, which only happens when your battery is running extremely low. Hmm, now that I know what it is called, and that it can be enabled (at this stage, only when your battery is running extremely low), I started looking for a way to enable it.

In the above article, it did list that there was a Standby Mode which would put MacBooks to deep sleep (aka hibernate to disk) however that happened only after the MacBook was in sleep mode for 3 hours! I was looking for something that will enable it much sooner. Below is the part in the above article referring to deep sleep.

Standby Mode

For Mac computers that start up from an internal SSD, macOS includes a deep sleep mode known as Standby Mode.

Mac computers manufactured in 2013 or later enter standby after being in sleep mode for three hours. Earlier models enter standby after just over an hour of sleep. During standby, the state of your session is saved to flash storage (SSD). Then, the power turns off to some hardware systems such as RAM and USB buses.

Standby extends how long a notebook computer can stay asleep on battery power. A notebook with a fully charged battery can remain in standby for up to thirty days without being plugged in to power.

After some trial and error, I managed to find the setting that will enable my MacBook Pro to go into “deep sleep/safe sleep/hibernate to disk” when it went into sleep mode.

These settings are enabled via the command pmset which is available via Terminal Here is some help with pmset

Start Terminal (Go to Finder/Go/Utilities/Terminal or use Spotlight Search and type Terminal)

To get your current power management settings run pmset -g custom

If for some reason, you mess up your power management settings, you can go to System Preferences/Energy Saver and click on Restore Defaults to get the default power management settings back


The settings that enable deep sleep/hibernate to disk is shown below



Use the command sudo pmset -b {option and value} to change any setting that you have which is different from the above values. (-b is to change settings for Battery Power, -c for AC power, -u for ups and -a for everything. I am using -b because I only want to enable hibernate to disk when I am running on battery)

For instance, if you want to change displaysleep for Battery Power from 2 to 5 use the following command

sudo pmset -b displaysleep 5

To check the settings again, run pmset -g custom

To test if hibernate to disk is now enabled, press Command+Option+Power together. Your MacBook should now go to sleep. Give it at least 20 seconds and then press the power button (this is how long I found it took my MacBook Pro to write the contents of RAM to disk. To be sure, you can put your ear to the keyboard, and if you still hear some sound, then it means that your MacBook is still writing to disk. Once everything has been written, it will be absolutely quiet). On waking up, you will see the Apple icon with a progress bar at the bottom. This shows that your MacBook is waking up from deep sleep.

MacOS Wake from Deep Sleep

Hope this helps others who are looking to enable true hibernation on their Macbook

Script to shutdown servers

I run a lot of Microsoft virtual machines in Azure and also locally on my MacBook Pro. These are my lab machines, which I use for testing.

One of the issues with having many virtual machines is orderly shutting them down. It can be a pain to go through each of them and shutting them down.

To circumvent this, I wrote a small PowerShell script, which does it all for me ūüôā

The script requires the following

$serverlist contains the hostnames of the servers that you want to shutdown (in the order they need to be shutdown)

$server_domainname this is the domain name that the servers are part of.

servername and and server_domainname is used to figure out the server fqdn, which is then used to shutdown that server.

Run the script from a computer that can connect to the servers. Ensure you are logged on as an account that has permissions to shutdown the servers.

The script will go through the list of servers contained in $serverlist and check if they are online. If they are online, then it will try to shut them down.

Do note that these servers will be forced to shutdown, so anything open on those servers will be lost, if not saved.

Once all the online servers have been shutdown, you will be asked if you want to shutdown the computer you are running the script from. You can press Enter to continue or CTRL+C to skip shutting down the computer you are logged on.

Hope this script comes in handy to others