Practical Phishing with Gophish

Setting up the Open-Source Phishing Framework Gophish on AWS to test your company’s phishing defences.

An Uru reed fish on Lake Titicaca, by me


I was recently asked to conduct phishing tests against our own AirWalk employees to assess our susceptibility to attack. We didn’t want to spend money engaging a third party testing company because, as a technology company, we thought we could probably do it ourselves.

In my previous story, Phishing Filosophy, I discussed the things one should consider before spamming colleagues with phoney emails, along with what form those messages should take.

Here I will discuss the practical implementation of the system I used to perform the test. This story will be more technically-focussed than the last.

I will describe all the technical steps I took in case you wish to do something similar to test your company’s defences. I would emphasise here, please ensure you have the authority from the correct people in your organisation before emulating anything I describe here. While I’m happy to respond to any questions, don’t blame me if you get fired :-)

Gone Phishing

Having previously answered all the questions of how I should form a phishing test email, I needed to choose a tool with which to create and send it. After some reading around I discovered Gophish, a piece of open-source software released under the the MIT License which handles the creation of email templates and landing pages, recipient lists, the actual email sending and campaign management. It feels a lot like an email marketing tool. Armed with this and a friendly SMTP relay I’d be on my way.

As is now natural, I decided to deploy Gophish to an EC2 instance in AWS.

I chose to use an AWS region that was far away from us here in London for two reasons. Firstly, to lower the chances of technical colleagues noticing my instance and suspecting a test was coming. Secondly, to add another little clue to the vigilant that this was going to be an unusual email should they choose to look at the headers. Therefore, I chose São Paulo.

View of downtown São Paulo, by me

Into the nitty gritty — EC2 setup

I logged myself into the EC2 console and selected the São Paulo (sa-east-1) region.

Select the São Paulo AWS region

As I hadn’t used the sa-east-1 region in this particular AWS account before, I had to import an SSH key pair into EC2.

Import an SSH key to EC2

Then I launched a new EC2 instance on which to run Gophish, following the various screens to configure the instance options.

Launch an EC2 instance

Step 1: choose AMI — I chose Amazon Linux 2, HVM with SSD

Choose EC2 AMI

Step 2: Instance type — t2.micro

(As an aside, I found the t2 micro to be perfectly adequate, so why pay more?)

Configure EC2 instance type

Step 3: Instance details — I selected the default VPC, choosing all default options for the instance details, including to assign a public IP (full details in the image below).
NB: If you have an existing non-default VPC , you would want to place the instance in a public subnet and choose to assign a public IP.

Configure EC2 instance details

Step 4: Storage — Storage was left at defaults; 8GB of storage on the root device will be plenty.

Configure storage

Step 5: Tagging — I added some appropriate tagging.

Configure EC2 tagging

Step 6: Security Groups: I created a new security group, allowing:
- HTTP (TCP/80) from anywhere — required for the pingbacks and to host landing pages
- HTTPS (TCP/443) from anywhere — same reasons as above
- SSH (TCP/22) from our office IP address
- TCP/3333 from our office IP address — this is the admin console for Gophish which I would use in my browser to control the campaigns

Configure EC2 security groups

Step 7: Review: I reviewed my settings (see below) and launched the instance — selecting my SSH key pair and accepting the terms.

Review EC2 instance settings before launch
Select keypair and launch instance

After waiting for the instance to launch, I allocated an Elastic IP address and associated it with my instance. This would help in case I needed to restart the instance for any reason as it needed to stay in one place once I started sending out emails with links to landing pages and pingbacks.

EC2 — associate Elastic IP
Associate Elastic IP with our instance

Installing Gophish

For the software installation, I followed the installation page of the Gophish User Guide.

Software installation

Once logged on to the instance via ssh, I needed to download a binary package for Gophish. In the browser on my laptop, I went to the Gophish releases page on GitHub and found the URL for the 64-bit Linux distribution by right-clicking (your browser experience may differ slightly).

Back on my instance, I created a user called gophish and downloaded the binary:

sudo adduser -c “Gophish user” gophish
sudo su — gophish
curl -L -o

Please note:

  • Do not simply copy paste my URLs above as there may be a newer version available since writing
  • Remember to use -L as the URL on the webpage doesn’t link directly to the binary, your curl will have to follow redirects

Then I created a directory for this version of Gophish and unzipped:

mkdir gophish-v0.7.1
cd gophish-v0.7.1/
unzip ../
rm ../

To make my life easier with future upgrades and startup scripts, I made a symbolic link to the current version:

ln -s /home/gophish/gophish-v0.7.1 /home/gophish/gophish

Gophish Configuration

Next, I inspected the config.json using my favourite editor:

“admin_server”: {
“listen_url”: “”,
“use_tls”: true,
“cert_path”: “gophish_admin.crt”,
“key_path”: “gophish_admin.key”
“phish_server”: {
“listen_url”: “”,
“use_tls”: false,
“cert_path”: “example.crt”,
“key_path”: “example.key”
“db_name”: “sqlite3”,
“db_path”: “gophish.db”,
“migrations_prefix”: “db/db_”,
“contact_address”: “”

admin_server -> listen_url

In order for the admin server to listen on our public IP address on TCP port 3333 (access to which was restricted to our office IP address in the security group rules above), I needed to update the admin_server -> listen_url to be

I chose to leave everything else at the defaults. While this configured HTTPS for our interaction with the admin server (Gophish creates this automatically), it still used unencrypted HTTP for any communication between email client and Gophish server. This could be switched to use HTTPS but would require an SSL certificate signed by a trusted certificate authority, otherwise recipients’ email clients would display a warning and give the game away. I therefore chose not to enable HTTPS now, as I would not be collecting data through forms, I would only be using the landing pages to display a message that this was a phishing test. However, I will cover how to configure HTTPS as an optional step in a future story.

I also chose to leave the database as sqlite. MySQL can be used, as described in the Installation page of the Gophish User Guide, if you believe that sqlite may not be enough for your needs, you wish to use RDS, or if you simply prefer it. Again, I will cover enabling Gophish with MySQL in a future story.

Startup Scripts

While I could have just started Gophish in an interactive shell, my preference was to start it as a service, meaning it would start at system boot. For this, I referred to this issue, linked from the installation page.

I adapted the script slightly to match my installation location so it became:

# /etc/init.d/gophish
# initialization file for stop/start of gophish application server
# chkconfig: — 64 36
# description: stops/starts gophish application server
# processname:gophish
# config:/opt/goapps/src/
# define script variables
start() {
echo ‘Starting ‘${processName}’…’
cd ${appDirectory}
nohup ./$process >>$logfile 2>>$errfile &
sleep 1
stop() {
echo ‘Stopping ‘${processName}’…’
pid=$(/usr/sbin/pidof ${process})
kill ${pid}
sleep 1
status() {
pid=$(/usr/sbin/pidof ${process})
if [[ “$pid” != “” ]]; then
echo ${processName}’ is running…’
echo ${processName}’ is not running…’
case $1 in
start|stop|status) “$1” ;;

Yes, it runs as root, but this is necessary to bind to port 80. You could configure your favourite webserver as a proxy in front of Gophish, but this is left as an exercise to the reader.

As I now needed to take some steps with sudo privilege, I exited my shell which was running as the gophish user:


I placed the above init script at /etc/init.d/gophish:

sudo vi /etc/init.d/gophish

(paste and save)

I changed the permission of this file to be a proper init script:

sudo chmod 744 /etc/init.d/gophish

I made Gophish start on boot:

sudo chkconfig gophish on

I created the log directory for Gophish that was referenced in the startup script:

sudo mkdir /var/log/gophish

I started Gophish:

sudo service gophish start

I checked the logs in /var/log/gophishand it seemed happy. I also checked the process was still up:

ps -ef |grep [g]ophish

That got me to the end of the Installation page, so I switched to following the Getting Started page

Getting Started using Gophish

In my browser, I connected via HTTPS to my Elastic IP address on port 3333:

I had to accept the self-signed certificate into my browser. Remember, this is just for the admin console, our email recipients won’t need to do this.

I logged in with the default credentials (admin / gophish)

The first thing I did was change the admin password via Settings

From here, I followed the main Documentation page of the Gophish user guide and set about creating a test group, containing just my own AirWalk email address, then creating a test email template and landing page. I won’t re-create the docs here, as I didn’t do anything they didn’t cover except:

  • To use an image in my landing page, I had to upload it to my server and put it in /home/gophish/gophish/static-endpoint— this directory is mentioned in the docs but didn’t exist, so I had to create it first.
  • It is covered in the documentation, but when setting up my email template, the template value of {{.URL}} is used to represent the landing page of your campaign, so when creating you HTML email template, click the link button and simply enter the URL exactly as {{.URL}}

Actually sending mail

When it came to creating a sending profile in Gophish, I had to go back to sysadmin thinking. How was I actually going to originate mail? Whose SMTP relay could I use?

“So when you’re near me, darling can’t you hear me, S.E.S.”

As I was originating my email in AWS, I thought I’d try Amazon’s own Simple Email Service (SES). I briefly considered whether my use case would be considered good enough by AWS Support to be allowed out of the SES Sandbox (In short, when you first start using SES, you’re in the “Sandbox”, which doesn’t allow you to send email to anyone except addresses you control. You have to ask AWS Support to permit you to send email to strangers). I figured if you don’t ask, you don’t get. Spoiler alert: it was all ok, so reading the next part isn’t a waste of your time.

SES doesn’t exist in São Paulo, so I chose the N.Virginia region as it was “close” (5,000 miles close).

In the SES console, I chose to Verify a New Domain, adding my domain and choosing to generate new DKIM settings:

Verify a new domain in SES

SES then displayed some values for me to add as TXT, MX and CNAME records to the DNS for my domain:

DNS settings for my domain to enable SES

Adding these records to my domain was trivial via my domain registrar’s control panel.

While I was editing the DNS for my fake domain, I decided to add an A record pointing to the Elastic IP address of our Gophish server, that would be useful later. A

After a very short time, the domain was showing as “Enabled for sending”.

My domain is enabled for sending

I then chose SMTP settings in the SES console to get the information I would need to add to the sending profile in Gophish.

I also had to click Create My Sending Credentials (as seen in blue above) to get some SMTP authentication credentials. This creates an SMTP username and password in the form of an IAM user with a key and secret key. I noted these down to put into Gophish later.

I was still in the SES Sandbox, so in order to perform some testing I needed to verify recipient domains to SES. I added my genuine company email address to “Email Addresses” in the SES console and verified it by clicking on the link in the email SES sent to me there.

Verify a recipient domain for SES testing

Back in Gophish, I now had what I needed to create a sending profile.

Create a new Gophish sending profile
  • From: I chose an arbitrary email address at my newly-purchased domain
  • Host: I used the SMTP server listed on the SES SMTP Settings page, with :25 for the port part
  • Username / password: The IAM-style credentials created and noted down earlier

I then chose to Send test email and Save profile

The test ended up in my junk folder, which led me to ask myself another question…

More Phishing Filosophy

Should we whitelist our “dodgy” domain in our corporate mail server?

The spam filter worked — the test email ended up in my junk folder with a warning that it looked suspicious, even though it didn’t even contain any links or attachments at this point. A topic I discussed in more detail in my earlier story, Phishing Filosophy, is whether I should deliberately remove this technological layer of protection for my phishing test domain. My conclusion was: of course! We know there is reasonable technology out there to block suspicious email and hopefully we’re all using some of it, but what we’re here to test are the people. Therefore, I whitelisted my copycat domain on our corporate mail server and re-sent the test. This time it landed in my inbox without any warnings. Boom.

Time for a campaign!

A campaign is where you can put it all together. I created a test campaign with the template, landing page and sending profile I created earlier.

My first Gophish campaign

Everything is fairly self-explanatory and the Campaign page in the User Guide explains it all.

For the URL, I used the hostname for our Gophish server that I setup as an A record in our DNS earlier.

After clicking Launch Campaign I had to accept a couple of times that I really wanted to launch my test campaign right now.

My email arrived in my work inbox. The link went through to my landing page and I could see the status of my campaign in the Gophish dashboard:

Gophish campaign results

Lose those training wheels

It was time to move out of the SES Sandbox. I sent a support request to AWS, requesting an SES service limit increase to 100 emails per day, which I didn’t think was too greedy, being totally honest about what I was intending to use their service for. Then, I had to wait for my ticket to be answered.

time passes

In a couple of days AWS had accepted my request and given me a limit of 50,000 messages per day. It was way more than I needed, but that was fine.

Giant Brown Trout, by me

Let’s catch some phish

Once everyone at AirWalk had confirmed they had completed the training, it was time to create a “real” campaign.

I chose a suitable target group within the company. How you choose to do this will depend on your organisation. Perhaps you’ll target everyone, perhaps a specific department, or perhaps a slice through various departments.

In the Gophish admin interface, I created a new group and used the Bulk Import Users option to upload a CSV file rather than having to key in everyone’s details by hand.

Create a new group in Gophish

As you will see if you download the example CSV template, the format is pretty straightforward:

First Name,Last Name,Email,Position

I left the job position empty as I won’t be using it and besides it was a faff to gather that information accurately. One thing that took me a while was to realise that I had to leave the column headings (from the template, as above) in the file on the first line otherwise it won’t take any data from the file.

Next, I created a more “realistic” email template, inviting my colleagues to read all about AirWalk’s Brexit planning via a link pertaining to be to our intranet. This was not an original idea, as phishers are known for choosing popular topics from current affairs to pique people’s interest and to distract them from considering the validity of the sender.

I also created a more interesting landing page, which clearly stated that the reader had participated in an AirWalk phishing test, but I still couldn’t resist having Matrix-style green rain falling in the background.

My phishing test landing page

I then created a new sending profile, created as a copy of the test one I created earlier, which means the SMTP server and authentication details were all pre-populated. The only thing I changed was the from address and friendly name, to be more appropriate to the content of the email.

With those complete, I could create a new campaign where I selected the new email template, landing page and sending profile.

Launch a new campaign in Gophish

Then I clicked Launch Campaign, confirmed my intent, and the fun began.

I could then monitor the campaign status in the campaign results page. As we can see, one person has clicked the link in the email already. Oops:

Gophish campaign status

The campaign results dashboard is where I spent a great deal of time in the minutes immediately after I sent the email. Here is an example of the results page from a test campaign. It shows a linear timeline above a representation of emails sent/opened/clicked as well as whether people had submitted data, if you had put a form on a landing page.

Example Gophish campaign results

Using the data from the dashboard, I pulled individuals into a private Slack channel as they each opened the email. In that channel I requested that they keep any conversation about the email to that specific place and not on more general channels or openly in the office.

Follow Up

At an all-hands meeting shortly after I ran the first company-wide phishing test, we had a constructive session where I presented the results. We discussed the various consequences of clicking bad links and opening malicious attachments and I went on to give practical advice on avoiding falling victim to phishing or other types of cyber attack. We have agreed to provide further training and run more tests in order to retain the level of phishing awareness in current and future staff.


I like Gophish and how easy it makes running a phishing test for your own company. We were correct in our initial assertion that we didn’t need to engage a third-party company to do this and it certainly didn’t take up a huge amount of time. I can still see why larger companies might outsource the whole thing, but if you’re reasonably technical and have the authority, you should certainly take a look at Gophish, particularly if you don’t currently have any form of phishing testing at all.

Phishing education, Jim-style