Make DNS Dynamic with Oracle Cloud

April 28, 2021 | 11 minute read
KC Flynn
Senior Cloud Engineer
Text Size 100%:

Overview

DNS is used to map a device’s IP address to a human-friendly domain name that is more easily memorable than a set of numbers (IPv4) or hexadecimal numbers (IPv6). The domain name associates a company’s brand with its online presence or abstracts a network endpoint from its IP address, and more. For clients on the internet to find a domain name, it must be published to an authoritative DNS server. Oracle Cloud provides access to these servers to manage essential to advanced DNS cases.

However, if the device mapped to the domain name moves or gets service from a provider that can’t issue a static IP address, the record mapping of that domain will need to be changed. Updating records manually is inefficient at best and infeasible at worst. An automated solution is required.

Luckily, all the automation needed to solve this problem is contained in Oracle Cloud Infrastructure. Using Oracle’s DNS service, serverless Functions, and API Gateway, we can automate your DNS changes. Avoid the need to rely on a Dynamic DNS provider by building one in Oracle Cloud Infrastructure.

 

Prerequisites


  • Docker
  • Fn Project CLI
  • An OCI environment, paid or 30 day trial
  • A domain name owned by you or your organization

 

Architecture


Solution Architecture Diagram

This architecture is based on a customer use case I ran across recently. An internet-connected device needed to receive data from a centralized application. The device was mobile and frequently moved between networks, which caused its IP address to change often. Using custom request headers, it was able to send messages to an OCI API Gateway at regular intervals to keep its IP address up to date and prevent service disruptions.

Other use cases that could use this architecture would be situations involving IoT, mobile computing, or in my case creating a static address for a home VPN endpoint.

 

Installation and Use


Prepare your OCI environment

  1. Log into the homepage of your OCI tenancy

  2. Navigate to the menu by clicking on the icon on the top left of the browser area and select Identity > Compartments Compartments on the OCI Console

  3. Click the Create Compartment button. Enter a display name and short description for your compartment. This will be the compartment resources for this project will be located in.

    • It is best practice to not use the root compartment to contain resources in the OCI tenancy. More information can be found here.
  4. Once the compartment is displayed on the list of compartments, click on the display name to view the details of the compartment. Click on the Copy link next to the OCID field to copy the compartment's OCID to your clipboard. Save this value as it will be used later. Compartment OCID Location

    • The OCID is the unique identifier for any resource in OCI
  5. Navigate to "Dynamic Groups" by selecting the link on the left side of the dashboard, or using the menu and selecting Identity > Dynamic Groups Dynamic Groups on the OCI Console

  6. Click the Create Dynamic Group button and give the Dynamic Group an appropriate display name and description. In the "Matching Rules" field, enter the following value replacing the placeholder field with the compartment OCID you copied in step 4.

    All {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..placeholdertext'}

    New Dynamic Group UI

    • This rule will match all Functions located in the specified compartment, giving them membership in the group. For more information on writing dynamic group rules to suit different use cases, read more here.
    • Giving the Function membership to this group will allow assigning OCI permissions without creating a service account and associated credentials. This gives our function the ability to alter DNS records.
  7. Navigate to the Policies dashboard by opening the menu and selecting Identity > Policies OCI Policies UI

  8. Click Create Policy and enter a display name and description for the policy. In the "Policy Builder" box, click Customize (Advanced) button and enter the following policies where KC_Dynamic_Group and kcflynn are the Dynamic Group and compartment created previously:

    Allow dynamic-group KC_Dynamic_Group to manage dns in compartment kcflynn
    Allow dynamic-group KC_Dynamic_Group to inspect vcns in compartment kcflynn

    OCI Screenshot

Create Network Resources

  1. Navigate to the menu in the top-left corner and select Networking > Virtual Cloud Networks Virtual Cloud Network UI
  2. Click the Start VCN Wizard button and then Start VCN Wizard with the VCN with Internet Connectivity radial button selected. VCN Wizard UI
  3. Enter a display name for your VCN and leave other options as their default values. Click Next and review the resources that will be created once the Create button is clicked.
  4. Click on the display name of the VCN to enter the VCN details page. On the left side of the page, underneath Resources, select Security Lists and click the Create Security List button.
  5. Give a descriptive name to the security list, such as "HTTPS", and click + Another Ingress Rule. Under Source CIDR enter 0.0.0.0/0 and in Destination Port Range enter "443" without quotes. Click the Create Security List button. Security List Settings
  6. On the left side under Resources select Subnets to view the public and private subnet created with the VCN. Click the display name of the public subnet to view the subnet details. Click the Add Security List button and select the Security List created in the previous step and click Add Security List. This will allow HTTPS traffic to the public subnet from the internet.

Add DNS Zone to OCI DNS Service

  1. From the menu, select Network > DNS ManagementDNS Management UI
  2. Select Zones from either the sub-menu on the left or the card under Manage DNS Services on the dashboard. OCI DNS Service UI
  3. Click the Create Zone button and add the zone with the method radial button set to ManualOCI Create Public DNS Zone UI
  4. Click Records under Resources on the left side of the zone information to view records that are created for the zone. This will include an SOA record and 4 NS records. Your registrar may have their own name servers which you will need to redirect to the name servers on this page. OCI DNS Zone UI

Create the Dynamic DNS Function

  1. Configure your choice of cloud or local development environment by following these instructions
  2. From the menu, select Developer Services > FunctionsOCI Serverless Functions UI
  3. Click the Create Application button and enter a display name for the function that will run the code to update the DNS Zone added in the last section. Make sure the VCN created earlier is selected, and choose the private subnet under Subnets.
  4. In your chosen command line environment, navigate to a working folder for this project and run the command fn init --runtime <Your Favorite Language> <Your Application Name> replacing the values in brackets <>.
  5. Write a bit of code to accomplish finding and updating your DNS recordings using Java, Python, JavaScript, .NET, Go, and/or Ruby SDKs. I was able accomplish the task fairly easily in Python, but any of the above should work fine. There's also a PL/SQL SDK but I wasn't able to conceptualize how I would work it into this architecture. Feel free to try if you can!
    self.dns_client = oci.dns.DnsClient({}, signer=signature)
    result = self.dns_client.patch_domain_records( zone_name,
    record_name,
    oci.dns.models.PatchDomainRecordsDetails(
    items=[ oci.dns.models.RecordOperation( operation='ADD',
    domain=record_name,
    ttl=record_ttl,
    rtype='A',
    rdata=record_content) ] ) )

    logger.debug("Update successful.")
    logger.debug("New rrset version: %s", result.data.items[0].rrset_version)
    logger.debug("Success")
  6. Run the command fn -v deploy --app <Your Application Name>. This will build the image with Docker with verbose output. If the Fn CLI context was set up correctly in step 1 this will upload the image to the OCI Container Registry.
  7. (Optional) Verify your Docker image was uploaded to Container Registry and a Function was created under the application in Step 3.
    • From the menu navigate to Developer Services > Container RegistryOCI Container Registry (OCIR) UI
    • From the menu navigate to Developer Services > Functions and select the display name of the application you created in Step 3. You should now see a function populated under FunctionsNew Function UI

(Optional) Create Validation Function

In a real environment, allowing anyone to add or update DNS records will not end well. There are several ways to secure access to functions with an API Gateway, including using other functions. Take a look at this example of how a function can be used to allow only requests that contain a pre-set key: Oracle Functions sample repository.

Create API Gateway

  1. From the menu, select Developer Services > API GatewayAPI Gateway on OCI Console
  2. Click the Create Gateway button and enter a display name for your gateway. Leave the Type set to Public, select the VCN created earlier, and select the public subnet within the VCN. Create API Gateway UI
  3. Once the API Gateway has been created, click the display name to inspect the details of the gateway. Click on the Deployments link under Resources on the left. New API Gateway
  4. Click on the Create Deployment button and enter a display name for the deployment and /v1 for the Path Prefix. API Deployment UI
  5. Click Next. Enter /dns for the Path, select POST in Methods, Oracle Functions for Type, and select the application and function created earlier. Click Next, review the deployment to be created, and click CreateAPI Routes UI

Putting It All Together

  1. Locate and copy the endpoint for your API Gateway on the details page of your API Gateway under ResourcesAPI Endpoint
  2. Use a tool like curl or Postman to sent a POST request to the endpoint with the desired A record to add or update in the 'x-record' header. I used a header field in the request to specify which record that needed updates. You could also do this in the request data, but I used headers.
    • Example: curl -v -X POST -H "x-record: host.domain.com" "<Endpoint>/dns"
    • Example: Postman Screenshot
  3. Look at your DNS Zone to see the A record added with the IP of the sender. From the menu navigate to Networking > DNS Management and select Zones. Select your DNS Zone and select Records under Resources on the left. You should see a new A record matching the value in the 'x-record' header of the request. DNS Zone Screenshot

In Conclusion


There are no two organizations that have the same circumstances and requirements for their IT environments. The strength of using the Cloud is to quickly and efficiently chain together different services to create a solution that meets your organization’s unique needs. Oracle Cloud gives that flexibility with services such as API Gateway, Functions, Events, and more. Take a look at Oracle Cloud Free Tier or a 30 day trial to find out what kind of solution you can build.

KC Flynn

Senior Cloud Engineer


Previous Post

Connecting securely from Oracle Integration to Autonomous database using network access list

Shreenidhi Raghuram | 5 min read

Next Post


Mapping to Unconventional JSON Objects in Oracle Integration

Siming Mu | 3 min read