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

My path to AWS Certified Solutions Architect – Associate

Almost a week and a half ago, I sat for and passed my AWS Certified Solutions Architect – Associate  (AWS CSAA) exam. To be quite honest, I felt the biggest sense of relief, after walking out of the exam centre, not because I had passed, but because I had finally forced myself to sit this exam.

Since posting on LinkedIn about passing my AWS CSAA exam, I have received a lot of requests from people, asking for tips on how to prepare for this exam. In addition to replying to them, I thought best to also put up a blog post, to help others that might be preparing to sit for the same exam.

I have been a Microsoft person for years, so it was quite natural for me to transition to Microsoft Azure a few years back. Microsoft Azure, to put it simply, is awesome. It empowers its users to grow their IT much faster and beyond what their local datacenter’s can accomodate, with a simple, pay-as-you-use model. This model has helped so many businesses become successful, in such a short amount of time.

I start my New Year, each year, with a list of technologies that I had been introduced to, in the year that had just finished, but did not get a chance to properly get acquainted with. This list, then condenses into my list of todos for that year. Last year, AWS made it into my list and since then I have been spending time, finding out all about it.

Exams to me are not just a certification, but a chance to find more about a technology and to re-confirm my understanding of it. That is why I try my best to learn as much as possible about the technologies being tested in an exam. What better way to learn more about AWS then to do the AWS Certified Solutions Architect – Associate exam 😉

I got my training material from Ryan Kroonenburg teaches an awesome course to get one prepared to sit for the exam. The course is not too expensive either, well within the budget of anyone.

However, a note of caution. If you are very new to AWS and think that just doing the course will be enough to pass the exam, then there is some news for you. The whole basis for the AWS exams is to test you on your hands on experience and just cramming the information and proceeding to sit for the exam will be preparing yourself for a fail. I would highly recommend doing the labs that Ryan takes you through in the course. AWS provides a free tier, which covers almost all that you will need to train for the AWS CSAA exam. You can make use of this to get lots of hands on training. Also, read the whitepapers and faqs. These provide detailed information about the AWS services. also has forums where you can ask questions and also answer questions others have posted.

To recap, my tips for passing the AWS CSAA exam

  • purchase the course for AWS CSAA
  • go through the videos in the course at least twice and do all the labs
  • answer all the section quizzes, the Mega Quizzes and Final exam questions and do them till you get at least 90% correct
  • read the AWS whitepapers and FAQs
  • participate in the forums

You will soon realise that you are confident enough to sit the exam and that is when you book it and go sit for it.

I would highly recommend not waiting too long to sit for your exam (I have learnt from my mistake). I find that if I wait for more than a month to book my exam, I normally start forgetting all that I have learnt, and have to go over the material all over again. Everyone is different, so this might not be true for you. I would suggest aiming for 1 month of training, however in the 2nd week, book your exam for a date 2 weeks away. Doing this will firstly put you in panic mode, but then you will soon realise that you don’t have much time to study, and will start studying more intensely. By the last week, if you still think you are not fully prepared, you have 72 hours to reschedule the exam. If you are going to reschedule, then don’t reschedule to a date too far in the future.

I wish you all the best for the exam.

MfaSettings.xml updates not taking effect

Last week, I was at a client site, extending their Microsoft Identity Manager (MIM) 2016 Self Service Password Reset Solution so that it could use Azure MultiFactor Authentication (MFA). This is an elegant solution since instead of using Questions and Answers to authenticate yourself when trying to reset your password, you can use One Time Passwords (OTP), sent as a security code via a text message to your registered mobile device.

I followed the steps as outlined in to enable Azure MFA, and everything went smoothly.

I then proceeded to testing the solution.

Using the Password Registration Portal, I registered my mobile number against my test user account.

I then opened the Password Reset Portal, entered my test user username and proceeded to wait for the text message from Microsoft Azure with the security code, so that I could enter it in the next screen.


I waited and waited (for at least 5 min), unfortunately the text message didn’t arrive 😦

Ok, troubleshooting time.

On my Microsoft Identity Manager 2016 Service Server, I opened the Windows EventLogs viewer and then expanded the section for Forefront Identity Manager event logs. Aha, I was on the right track as I saw a lot of errors reported.


I went through the event log entries and found one which looked abit odd. The error essentially said that the certificate path contained illegal characters.


I couldn’t make much sense of this error, so I opened the MfaSettings.xml file to check, and I quickly realised my mistake. I had included the certificate file path within quotes!

I quickly removed the unnecessary ” “ , saved the MfaSettings.xml file and restarted my testing process.

I went through the password reset process again, and yet again, I didn’t receive any text message from Microsoft Azure with the security code 😦

I re-checked the eventlogs and noticed the same Exception: Illegal characters in path for the Certificate File Path error. Thinking that I might have forgotten to save the previous modification to the MfaSettings.xml file, I opened the file to confirm. The quotes were no where to be seen! Alas, the plot thickens my dear Watson!

I couldn’t find any explanation for this behaviour. Then, thinking that maybe the MIM server was having issues accessing the long filepath for the Certificate file, I moved the certificate file to a folder that was closer to the root of the C:\ drive, updated the MfaSettings.xml file appropriately and repeated my testing.

Again, no text message 😦

Checking the event logs, I noticed the same dreaded Exception: Illegal characters in path for the Certificate File Path error again.

However, looking closer at the error, I realised that the file path was reported as C:\Program Files\Microsoft Forefront Identity Manager\2010\Service\MfaCerts\cert_key.p12, which wasn’t correct since I had moved the certificate file to another folder and updated the MfaSettings.xml file accordingly!

Suddenly I had that light bulb moment 😉 Updates to the MfaSettings.xml file were not being read by the MIM Server! This could only mean that it wasn’t monitoring this file for any changes, quite the opposite to what I had initially assumed!

To force MIM to re-read the MfaSettings.xml file, I restarted the Forefront Identity Manager Service service and went through my password reset testing process again.

Eureka! This time around, I received the text message from Microsoft Azure with the security code! Checking the Event logs, I couldn’t find any new occurrences of the Exception: Illegal characters in path for the Certificate File Path error. Hurray!

I completed the password reset process and confirmed that the password for my test account had indeed been changed.

I hope this post helps others.

BTW, below is a sample of the MFASettings.xml file (for security reasons, the keys have been scrambled, however as seen below, none of the values need quotes)

<?xml version=”1.0″ encoding=”utf-8″ ?>
<CertFilePath>C:\Program Files\Microsoft Forefront Identity Manager\2010\Service\MfaCert\cert_key.p12</CertFilePath>


Re-execute the UserData script in an AWS Windows Instance

Bootstrapping is an awesome way of customising your instances in AWS (similar capability exists in Azure).

To enable bootstrapping, while configuring the launch instance, in Step 3: Configure Instance Details scroll down to the bottom and then expand Advanced Details.

You will notice a User data text box. This is where you can provide your bootstrap script. The script will be run when your instance is first launched.


I went ahead and entered my script in the text box and proceeded to complete my instance configuration. Once my instance was running, I initiated a Remote Desktop connection to it, to confirm that my script had run. Unfortunately, I couldn’t see any customisations (which meant my script didn’t run)

Thinking that the instance had not been able to access the user data, I opened up Internet Explorer and then browsed to the following url (this is an internal url that can be used to access the user-data)

I was able to successfully access the user-data, which meant that there were no issues with that.  However when checking the content, I noticed a typo! Aha, that was the reason why my customisations didn’t happen.

Unfortunately, according to AWS, user-data is only executed during launch (for those that would like to read, here is the official AWS documentation). To get the fixed bootstrap script to run, I would have to terminate my instance and launch a new one with the corrected script (I tried re-booting my windows instance after correcting my typo, however it didn’t run).

I wasn’t very happy on terminating my current instance and then launching a new one, since for those that might not be aware, AWS EC2 compute charges are rounded up to the next hour. Which means that if I terminated my current instance and launched a new one, I would be charged for 2 x 1hour sessions instead of just 1 x 1 hour!

So I set about trying to find another solution. And guess what, I did find it 🙂

Reading through the volumes of documentation on AWS, I found that when Windows Instances are provisioned, the service that does the customisations using user-data is called EC2Config. This service runs the initial startup tasks when the instance is first started and then disables them. HOWEVER, there is a way to re-enable the startup tasks later on 🙂 Here is the document that gives more information on EC2Config.

The Amazon Windows AMIs include a utility called EC2ConfigService Settings. This allows you to configure EC2Config to execute the user-data on next service startup. The utility can be found under All Programs (or you can search for it).



Once Open, under General you will see the following option

Enable UserData execution for next service start (automatically enabled at Sysprep) eg. or <powershell></powershell>


Tick this option and then press OK. Then restart your Windows Instance.

After your Windows Instance restarts, EC2Config will execute the userData (bootstrap script) and then it will automatically remove the tick from the above option so that the userData is not executed on subsequent restarts (or service starts)

There you go. A simple way to re-run your bootstrap scripts on an AWS Windows Instance without having to terminate the current instance and launching a new one.

There are other options available in the EC2ConfigService Settings that you can explore as well 🙂