OPNsense, like pfSense, is an open source FreeBSD-based network firewall distribution. The world of the public cloud is dominated by Linux and Windows VMs, so network administrators deploying a FreeBSD image for the first time often ask “how to do it?” Like we explained in our earlier article about the OPNsense project, you have the option of using a “pre-baked” image from the AWS Marketplace listed by Deciso, the company that is the lead maintainer for OPNsense. Since that is a Marketplace AMI, it incurs an hourly fee (licensing cost) additional to the cost of the EC2 instance. This cost also scales up based on the EC2 instance type that you choose (i.e. increases as you require more routing capacity).
Note that the Marketplace AMI is not the Business Edition of OPNsense available from the Deciso web shop which entitles the user to additional support and features. The marketplace offering is simply the community code packaged as an AMI; You must still purchase a license key if you wish to upgrade an OPNsense firewall deployed using the AMI to the Business Edition.
As open source software, the community edition of the OPNsense software is completely free to use – only the AWS Marketplace AMI or Azure Marketplace product incurs a cost. In this article, we will discuss how to upload the official OPNsense image to AWS and create our own private AMI – which does not incur an hourly cost. This is entirely legal, and in compliance with the open source BSD license that OPNsense itself is released under.
We think it is much wiser to build your own AMI (in fact, some corporate policies require it) that is not exposed to an arbitrary price increase (at one point, pfSense increased the hourly pricing of its marketplace image by 50%) and support Deciso directly if you wish by licensing the Business Edition. Also, this approach creates the possibility of deploying OPNsense on other cloud providers (e.g. Oracle Cloud) than AWS or Azure – which do not have a marketplace listing for OPNsense. The private AMI can receive updates through the web GUI and package manager; it is equivalent to the marketplace AMI.
Our team of network architects and specialists also provide support with planning your cloud VPC deployment and securing its perimeter with OPNsense and its add-ons. Feel free to get in touch for consulting, implementation support, and maintenance. We are excited to share our knowledge in architecting a robust AWS (or other cloud) environment – allocating the CIDR ranges of your IP subnets for security, peering with multi-cloud or on-prem networks, and allowing for the future growth of your applications.
Import OPNsense Image as Snapshot using AWS VM Import/Export Tool
On your local machine or AWS Cloud Shell, download the latest OPNsense image. If using AWS Cloud Shell, it is recommended to download the image in the /tmp directory as the persistent home directory is limited to 1 GB.
$ curl -O https://opnsense-mirror.hiho.ch/releases/24.7/OPNsense-24.7-nano-amd64.img.bz2 OPNsense-24.7-nano-amd64.img.bz2
Extract the OPNsense .img from the .img.bz2 using the bzip2 -d
command.
$ bzip2 -d OPNsense-24.7-nano-amd64.img.bz2
Rename the .img to the .raw extension and upload it to an S3 bucket and make the object publicly accessible. This bucket should be in the same AWS region as where you plan to create the AMI. You will need to turn off the Block Public Access feature that applies on a bucket-wide basis.
If you downloaded the image in the AWS Cloud Shell running the same region as your AWS bucket, then you can simply upload the extracted image to S3 from there – as the Cloud Shell is already pre-authenticated for the AWS CLI commands.
$ aws s3 cp /tmp/OPNsense-24.7-nano-amd64.raw s3://opnsense-imgs/
Import the IMG as a snapshot in RAW format using AWS VM Import/Export tool. From the AWS Cloud Shell, create a file called containers.json in your working directory.
{ "Description": "OPNsense 24.7", "Format": "RAW", "UserBucket": { "S3Bucket": "opnsense-imgs", "S3Key": "OPNsense-24.7-nano-amd64.raw" } }
Then, begin the import with the following command in the AWS Cloud Shell.
$ aws ec2 import-snapshot --description "OPNsense 24.7" --disk-container "file://containers.json"
You can monitor that the import has completed successfully by using the "ImportTaskId": "import-snap-04e7986a76a0b2bcc",
that was returned when invoking the aws ec2 import-snapshot
command. Notice that the “Status” key should read “completed”.
$ aws ec2 describe-import-snapshot-tasks --import-task-ids import-snap-04e7986a76a0b2bcc { "ImportSnapshotTasks": [ { "Description": "OPNsense 24.7", "ImportTaskId": "import-snap-04e7986a76a0b2bcc", "SnapshotTaskDetail": { "Description": "OPNsense 24.7", "DiskImageSize": 3221225472.0, "Format": "RAW", "SnapshotId": "snap-0e77c025d346fb957", "Status": "completed", "UserBucket": { "S3Bucket": "opnsense-imgs", "S3Key": "OPNsense-24.7-nano-amd64.raw" } }, "Tags": [] } ] }
Convert the Snapshot to an AMI, then launch the OPNsense EC2 instance
Create an AMI from the snapshot in the AWS Management Console.
Launch an EC2 instance from the snapshot in the AWS Management Console.
Configure the VPC, Subnets, Network Interfaces, and Route Table in AWS Management Console
Configure Public and Private Subnets in VPC. The IP ranges of the subnets used in this example are:
- public-subnet –
172.31.32.0/20
(172.31.32.1-172.31.47.254) - private-subnet –
172.31.48.0/20
(172.31.48.1-172.31.63.254)
Create Security Groups for the public and private subnets. The public subnet should allow access from your office or home IP to ports 443, 8443, and 22. The private subnet allows all traffic (firewall rules are controlled from within OPNsense).
Assign an Elastic IP to the default ENI for WAN.
Create an additional ENI for LAN. Turn off source/destination check. The ENI for the WAN has already been created by default when you launched the EC2 instance.
Create a route table for private subnet (LAN) routing 0.0.0.0/0 to the LAN ENI. Assign it to the private subnet.
The public subnet (WAN) can use the default route table which routes 0.0.0.0/0 to an Internet gateway.
Set up Web GUI, SSH Access, and NAT Port Forwarding Rules in OPNSense
Start the EC2 instance and prepare to connect to the serial console (must be Nitro instance type such as a t3, not a t2 instance). We recommend at least a t3.large if you plan to use the Intrusion Detection features (otherwise it may run out of resources while loading IDS rulesets).
Attach the additional private ENI to the EC2 instance.
Notice that the public (WAN) ENI is assigned the private IP address 172.31.41.155
in the 172.31.32.0/20
range of the public subnet and the private (LAN) ENI is assigned the private IP 172.31.55.209
in the 172.31.48.0/20
IP range of the private subnet.
Turn off source/destination check for the instance.
Once connected to the EC2 serial console (the default username is “root” and password is “opnsense”); From the OPNsense console, configure the WAN network interface only (ena0 for WAN).
Enter an option: 1 Do you want to configure LAGGs now? [y/N]: N Do you want to configure VLANs now? [y/N]: N Valid interfaces are: ena0 0a:48:1e:f4:d8:9b ENA adapter If you do not know the names of your interfaces, you may choose to use auto-detection. In that case, disconnect all interfaces now before hitting 'a' to initiate auto detection. Enter the WAN interface name or 'a' for auto-detection: ena0 Enter the LAN interface name or 'a' for auto-detection NOTE: this enables full Firewalling/NAT mode. (or nothing if finished): Enter the Optional interface 1 name or 'a' for auto-detection (or nothing if finished): The interfaces will be assigned as follows: WAN -> ena0 Do you want to proceed? [y/N]: Y
Install nano using pkg install nano
, and disable referrer check in /conf/config.xml. Add <nohttpreferercheck>1</nohttpreferercheck>
to the <webgui>...</webgui>
section of /conf/config.xml
Login to the web GUI at https://<EIP>:443/ with the default username (root) and password (opnsense).
Change the default user and pass and supply a public key for SSH.
Change the Web GUI port from 443 to 8443. 443 should be reserved for the reverse proxy (e.g. NGINX or HAProxy) for web applications.
Enable the Secure Shell daemon and tick “allow root login”.
Create (and apply) NAT port forwarding rules allowing all traffic to port 8443 and 22 to be NAT through to the private IP address of your WAN interface (e.g. 174.31.41.155)
From the serial console or SSH, assign both network interfaces (ena0 for WAN and ena1 for WAN). Then, configure a static IP for the LAN (e.g. 174.31.55.209 with subnet mask 20).
Enter an option: 1 Do you want to configure LAGGs now? [y/N]: N Do you want to configure VLANs now? [y/N]: N Valid interfaces are: ena0 0a:48:1e:f4:d8:9b ENA adapter ena1 0a:ff:e6:9c:96:cd ENA adapter If you do not know the names of your interfaces, you may choose to use auto-detection. In that case, disconnect all interfaces now before hitting 'a' to initiate auto detection. Enter the WAN interface name or 'a' for auto-detection: ena0 Enter the LAN interface name or 'a' for auto-detection NOTE: this enables full Firewalling/NAT mode. (or nothing if finished): ena1 Enter the Optional interface 1 name or 'a' for auto-detection (or nothing if finished): The interfaces will be assigned as follows: WAN -> ena0 LAN -> ena1 Do you want to proceed? [y/N]: Y
Enter an option: 2 Available interfaces: 1 - LAN (ena1 - static, track6) 2 - WAN (ena0 - dhcp, dhcp6) Enter the number of the interface to configure: 1 Configure IPv4 address LAN interface via DHCP? [y/N] N Enter the new LAN IPv4 address. Press for none: > 172.31.55.209 Subnet masks are entered as bit counts (like CIDR notation). e.g. 255.255.255.0 = 24 255.255.0.0 = 16 255.0.0.0 = 8 Enter the new LAN IPv4 subnet bit count (1 to 32): > 20 For a WAN, enter the new LAN IPv4 upstream gateway address. For a LAN, press for none: > Configure IPv6 address LAN interface via WAN tracking? [Y/n] Do you want to enable the DHCP server on LAN? [y/N] Do you want to change the web GUI protocol from HTTPS to HTTP? [y/N] Do you want to generate a new self-signed web GUI certificate? [y/N] Restore web GUI access defaults? [y/N] Writing configuration...done. Generating /etc/resolv.conf...done. Generating /etc/hosts...done. Configuring LAN interface...done. Setting up routes for lan...done. Starting DHCPv6 service...done. Starting router advertisement service...done. Starting Unbound DNS...done. Configuring firewall.......done. Starting DHCPv6 service...done. Starting router advertisement service...done. You can now access the web GUI by opening the following URL in your web browser: https://172.31.55.209:8443
Note that you cannot really access the web GUI from the private IP address displayed (172.31.55.209:8443) since the client machine you are working from is not on the same network as the AWS VPC. Instead, in your browser, use the publicly routable elastic IP https://<EIP>:8443
of the OPNsense instance which is automatically NATed through to that internal IP based on the port forward rule you set up earlier.
Once you have done so correctly, the OPNsense console should look something like this:
*** OPNsense.localdomain: OPNsense 24.7.6 *** LAN (ena1) -> v4: 172.31.55.209/20 WAN (ena0) -> v4/DHCP4: 172.31.41.155/20 HTTPS: sha256 58 F8 9E 24 61 EE 27 5D E5 E3 CA 8D 15 C5 90 67 9D F5 6F EC E2 D5 5F DA D4 1D 16 35 31 BF BE CC SSH: SHA256 kGJY1O05gLa6yoXS1pHX/jRrxHLmIGOFnwA1cIUx4RE (ECDSA) SSH: SHA256 KNEgWLGJ+4HDDrg8SUN6Z7plbp9JUdOnFheBG93xFI0 (ED25519) SSH: SHA256 gXUIryFKsax/+vRan91hTTidfFHisdZKDeRvXJNOsrk (RSA)
Restart the EC2 instance and check that you still have web GUI and SSH access. If you are locked out of the web GUI or SSH, detach the LAN ENI by right-clicking on the EC2 instance in the AWS Console. Then, restart the instance and try the above steps again.
Convert the OPNsense IMG to VMDK and Deploy on Oracle Cloud (OCI) – using the VBoxManage or qemu-img utilities
A similar procedure can be followed to deploy the OPNsense image in Oracle Cloud (OCI), but instead of using the RAW format, OCI requires a VMDK to create a custom image – equivalent to an AMI. Fortunately, the VBoxManage utility (installed with the open source VirtualBox maintained by Oracle) or qemu-img (available as part of the qemu package from your distribution’s package manager) can easily convert .img to .vmdk format.
$ brew install qemu OR $ apt install qemu $ curl -O https://opnsense-mirror.hiho.ch/releases/24.7/OPNsense-24.7-nano-amd64.img.bz2 OPNsense-24.7-nano-amd64.img.bz2 $ bzip2 -d OPNsense-24.7-nano-amd64.img.bz2 $ qemu-img convert -O vmdk OPNsense-24.7-nano-amd64.img OPNsense-24.7-nano-amd64.vmdk OR $ VBoxManage convertfromraw OPNsense-24.7-nano-adm64.img OPNsense-24.7-nano-amd64.vmdk --format VMDK
An important limitation to note is that the “Always Free” instance shape with 1/8 AMD EPYC oCPU / 1 GB RAM only supports 1 VNIC. This prevents a both WAN and LAN interface from being attached, limiting the usefulness of OPNsense as a router. For this reason, we recommend using a “paid” instance type for deploying OPNsense on OCI. The standard (paid) instance types support a minimum of 2 VNICS with 1 OCPU, and 1 VNIC/OCPU up to a maximum of 24 VNICs for instances configured with 2 – 24 OCPUs.
Your Oracle Cloud account must be upgraded to a paid account to create custom images and use instance shapes that support > 1 VNIC.
Like with AWS, you must first upload the .vmdk to Object Storage (Oracle’s counterpart to S3) in a bucket of the same compartment as where you plan to create the custom image. Then, you will be able to create the custom image with the following settings:
- Operating system: Generic Linux
- Import from an Object Storage bucket
- Bucket name
- Object name
- Image type: VMDK
- Launch mode: Paravirtualized
A work request will be created, and once the VMDK completes importing to the custom image, you can launch a compute instance running the OPNsense image in the compartment of your choice. Once the instance is up-and-running, you can use the Oracle Cloud Shell to establish a serial connection to the instance to assign the network interface(s) and edit /conf/config.xml to disable the referrer check to access the Web GUI.
For more information about configuring additional subnets, security lists (analogous to security groups in AWS), and the LAN VNIC (analogous to ENI in AWS), get in touch with one of our consultants knowledgeable in OPNsense for assistance. If you are familiar with the differences between AWS and OCI, then the steps for AWS beginning from “Configure Public and Private Subnets in VPC” can be easily adapted for use with configuring your VPC with OPNsense in OCI. Later, we may publish a subsequent article discussing the specifics of deploying OPNsense in an OCI VPC.