Upgrading to the Canon 5D Mark IV from a Canon 6D

I recently upgraded my camera from the Canon EOS 6D to the Canon EOS 5D Mark IV. When I was doing my initial research, I didn’t see many people talking about their transition experiences – so I thought I’d write something up.

GPS Mode

One of the handiest features for me whilst travelling is having GPS tagging on my photos. On walks, I tend to take a quick snap of markers (like direction markers or informative boards), so when I can load up the photos from the trip in Lightroom’s Map view when I get home and re-trace my steps.

My 6D was the first DSLR I’ve owned that has had GPS built in. It served its purpose well but Canon made one interesting design choice: the GPS stays active (and drains precious battery) even when the camera is switched off (including via the physical switch). Many times, I’ve woken up in the morning with a flat camera battery because I’ve forgotten to fiddle through menus and turn off the GPS during the previous evening.

On my 5DMkIV, there are two modes for the GPS feature. There is Mode 1 which acts exactly like the 6D (where the GPS is always-on as long as there is life in the battery), and then Mode 2 which switches the GPS off when the physical power switch is set to Off. Mode 2 is perfect for a day of travelling and photography. You do need to be aware of the drawback, however, which is that the camera may not have a GPS lock when you got to take a photo immediately after powering up.

Touch Screen

I didn’t really think I’d be using the touch-screen much when I first decided to upgrade. However, even on Day 1, I found myself using it quite a bit – both for toggling AF point modes during shooting, as well as pinch-to-zoom for previewing photos. It’s honestly very refreshing (though I probably do need to play more with the physical controls – which I’ve read can be quite a bit faster).

ISO Button Placement

When shooting in manual mode, I tend to use the ISO button on the top of the camera to change ISO. On the 5DMkIV, I noticed that the placement of the buttons varies just enough, with muscle memory trained on the 6D, to have me pressing the “DRIVE AF” toggle instead. It’s something I’ll get used to in a few more hours of use, but just a small source of (temporary) frustration for a new user.

You can see this illustrated somewhat in the photo below:

That’s it for now, but I’ll keep updating this post as I have an opportunity to use my new camera more!

Setting up pfSense with IPv6

I recently had the opportunity to redesign my home network (including with dual-stack IPv6). My setup is as follows:

Physical Devices

Logical Setup

  • A “secure” VLAN – for ‘trusted’ devices.
  • A “restricted” VLAN- for devices on my wireless network and ‘untrusted’ wired devices (i.e. smart TV’s).

On the IPv4 side, this is the usual NAT setup, with each network having a separate private /24 subnet. IPv6 was a little different – essentially my ISP provides a /56 prefix of IPv6 address via DHCP. Given IPv6 minimum subnet sizes of /64, this gives me 8 bits to play with (i.e. I can therefore have 256 /64 networks. Therefore, my IPv6 network followed this model:
[ISP 56-Bits]:[My Subnet 8-Bits]:[My Device Address 64-Bits] = 128-bit IPv6 address.

Interesting Findings

  • Chromecast support across multiple VLANs on both IPv4 and IPv6 required:
    • Installing the Avahi pfSense package. The default settings seem to work fine to make the Chromecasts discoverable – but I noticed Avahi can crash every now and then, so I set up the separate Service Watchdog pfSense package to reboot it if it crashes.
      avahiservice_watchdog
    • Ensuring each Chromecast received a static IP address, ensuring no firewall rules block access to the Chromecast devices across subnets and ensuring multicast UDP traffic was allowed to flow freely to IPv4 (224.0.0.0/4) and IPv6 (ff00::/8)
      multicast_firewall
  • To ensure IPv6 works effectively when you’re running in stateless mode (SLAAC), you can no longer set Windows desktops / servers to “block all incoming” connections on the host firewall. If you do this, you’ll end up blocking in the inbound router advertisement (RA) packets that set ups the IPv6 default gateway. E.G.:
    windows_firewall
  • When I first set up IPv6 DNS servers for IPv6 connections, I noticed that there was a big latency difference between IPv4 Google Public DNS (<4ms from Sydney) and IPv6 Google Public DNS (~200ms latency). Between my first draft of this post and me publishing it, this appears to have been resolved - with Google confirming they’ve extended the geographic range of Google Public DNS out to Australia (my IPv6 DNS pings are now ~4ms, the same as IPv4)
  • When I first tested my IPv6 connectivity, I was using the two major test sites (Exhibit A | Exhibit B). I noticed one generally gave me a 18/20 despite everything looking good. When I did some more reading, I discovered that IPv6 requires you to allow certain types of ICMP traffic inbound from the public internet (which you didn’t need in an IPv4-only world). Most operating-system host firewalls still block it though(!). Based on section 4.3.1 of the IETF spec, I’ve unblocked the 6 types of ICMP traffic that “MUST NOT be blocked”:
    ietfpfsense_wan

Protect S3 Data from Deletion using Multi-Factor Authentication

One of the interesting features available in Amazon S3 is Multi Factor Authentication Delete.

This features allows you to specify a TOTP-compatible virtual MFA device or a physical MFA device and link it to a versioned S3 bucket. This means that any future attempt to change the versioning state of the bucket, or delete any version of a file from a bucket MUST be accompanied with a valid token code. (You can’t delete the entire bucket object either – as you can’t delete a bucket holding any files/versions.)

This is especially useful in environments where you want to store security-related audit/event/log data – especially where some level of dual-control and/or physical segregation is required.

When I was trying to see what was available to do this, I looked at a couple of GUI solutions which supported it – however I wanted a scriptable version that could be used in automation scripts. In my case, it was designed to be manually executed by two custodians (one holding the AWS root account credentials, and one holding the physical MFA token). Theoretically, this could be fully automated by having a virtual TOTP application or HSM.

The process to set-up prerequisites is simple:

  1. Install Ruby – I tend to ensure it can run Ruby scripts (.rb files) and is available in PATH.
  2. Install the AWS SDK for Ruby by typing gem install aws-sdk in a command line.
  3. Save the script provided below as a Ruby (.rb) script file
  4. Execute the script by following the usage instructions described below.

Usage

Structure: 
> enable-mfa-delete-s3.rb ACCESS_KEY SECRET_KEY S3_BUCKET_NAME AWS_ACCOUNT_ID AWS_REGION AWS_TOKEN_CODE

Example: 
> enable-mfa-delete-s3.rb AAAAAAAA BBBBBBBB my-first-s3-bucket 123456789 ap-southeast-2 123456

Script

require 'rubygems'
require 'aws-sdk'

# Fix SSL problem on Windows + Ruby: https://github.com/aws/aws-sdk-core-ruby/issues/166
Aws.use_bundled_cert!

# Read script arguments.
aws_access_key 		= ARGV[0].to_s
aws_secret_key 		= ARGV[1].to_s
aws_bucket_name		= ARGV[2].to_s
aws_account_id 		= ARGV[3].to_s
aws_region 		= ARGV[4].to_s
aws_token_code 		= ARGV[5].to_s

# Create a client object to interface with S3.
client = Aws::S3::Client.new(region: aws_region, :access_key_id => aws_access_key, :secret_access_key => aws_secret_key)

# Assemble the MFA string.
aws_mfa_device_string = 'arn:aws:iam::' + aws_account_id + ':mfa/root-account-mfa-device ' + aws_token_code

# Update the bucket versioning policy.
client.put_bucket_versioning({
  bucket: aws_bucket_name, # required
  mfa: aws_mfa_device_string,
  versioning_configuration: { # required
    mfa_delete: "Enabled", # accepts Enabled, Disabled
    status: "Enabled", # accepts Enabled, Suspended
  },
  use_accelerate_endpoint: false,
})

# Output the new state.
resp = client.get_bucket_versioning({
  bucket: aws_bucket_name, # required
  use_accelerate_endpoint: false,
})

print 'Bucket Name: ' + aws_bucket_name + "\n"
print 'Versioning Status: ' + resp.status + "\n"
print 'MFA Delete Status: ' + resp.mfa_delete + "\n"

Full credit to the people who’ve posted their Ruby-based solutions [1] [2] previously (but no longer seem to work given changes to the AWS SDK and/or Ruby.)