Skip to content

Instantly share code, notes, and snippets.

@anubhavg-icpl
Created September 21, 2024 05:12
Show Gist options
  • Save anubhavg-icpl/56d29f8924dd553a6c2010e3b9b7106f to your computer and use it in GitHub Desktop.
Save anubhavg-icpl/56d29f8924dd553a6c2010e3b9b7106f to your computer and use it in GitHub Desktop.

CoreDNS Setup for Local Network with SSL

Table of Contents

  1. Introduction
  2. System Architecture
  3. Prerequisites
  4. Installation
  5. Configuration
  6. SSL Configuration
  7. Troubleshooting
  8. Advanced Usage
  9. Contributing
  10. License

Introduction

This project sets up a local DNS infrastructure using CoreDNS, with one Debian server acting as the DNS server and two client VMs. The system is designed to use CoreDNS for local hostname resolution and fall back to 1.1.1.1 for internet queries. Additionally, it includes SSL configuration for secure local connections.

System Architecture

graph TD
    A[CoreDNS Server] -->|DNS Queries| B(Client VM 1)
    A -->|DNS Queries| C(Client VM 2)
    A -->|Fallback| D{Internet DNS 1.1.1.1}
    B -->|SSL| E[Local Services]
    C -->|SSL| E
Loading

Prerequisites

  • 1 Debian VM for CoreDNS server
  • 2 Client VMs (any Linux distribution)
  • Root or sudo access on all VMs
  • Basic understanding of DNS and networking

Installation

CoreDNS Server Setup

  1. Download and install CoreDNS:

    wget https://github.com/coredns/coredns/releases/download/v1.10.1/coredns_1.10.1_linux_amd64.tgz
    tar xzf coredns_1.10.1_linux_amd64.tgz
    sudo mv coredns /usr/local/bin/
  2. Verify installation:

    coredns -version

Client VM Configuration

On each client VM, edit the /etc/resolv.conf file:

sudo nano /etc/resolv.conf

Add the following content (replace 192.168.1.10 with your CoreDNS server's IP):

nameserver 192.168.1.10
nameserver 1.1.1.1

Configuration

CoreDNS Configuration File

Create and edit the Corefile:

sudo mkdir /etc/coredns
sudo nano /etc/coredns/Corefile

Add the following content:

.:53 {
    hosts {
        192.168.1.10 server.local
        192.168.1.20 client1.local
        192.168.1.30 client2.local
        fallthrough
    }
    forward . 1.1.1.1
    log
    errors
}

SystemD Service Setup

Create a SystemD service file:

sudo nano /etc/systemd/system/coredns.service

Add the following content:

[Unit]
Description=CoreDNS DNS server
After=network.target

[Service]
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable coredns
sudo systemctl start coredns

SSL Configuration

Generate a self-signed certificate:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
     -keyout /etc/ssl/private/hostname.local.key \
     -out /etc/ssl/certs/hostname.local.crt

Follow the prompts, ensuring you set the Common Name to "hostname.local".

Troubleshooting

If CoreDNS fails to start, try the following:

  1. Check permissions:

    ls -l /usr/local/bin/coredns
    sudo chmod +x /usr/local/bin/coredns
  2. Verify Corefile:

    cat /etc/coredns/Corefile
  3. Run CoreDNS manually:

    sudo /usr/local/bin/coredns -conf /etc/coredns/Corefile
  4. Check logs:

    sudo journalctl -u coredns.service
  5. Check for port conflicts:

    sudo lsof -i :53
  6. Configure firewall:

    sudo firewall-cmd --permanent --add-service=dns
    sudo firewall-cmd --reload

Advanced Usage

  • Custom DNS records: Add more entries to the hosts section in the Corefile.
  • Plugins: CoreDNS supports various plugins. Explore the official documentation for more options.
@anubhavg-icpl
Copy link
Author

I understand you want to set up CoreDNS on your VMs with one Debian server for CoreDNS and two clients. You want to configure it so that if a hostname pings successfully, it uses CoreDNS for communication, and if not, it passes the request to the internet using 1.1.1.1 as the DNS server. Your main goal is to bind SSL using hostname.local.

Let's break this down into steps:

  1. Set up CoreDNS server on Debian VM
  2. Configure two client VMs
  3. Configure CoreDNS for local resolution and fallback to 1.1.1.1
  4. Set up SSL for hostname.local

Let's start with the CoreDNS server setup:

  1. Set up CoreDNS server on Debian VM:

First, install CoreDNS on your Debian VM:

wget https://github.com/coredns/coredns/releases/download/v1.10.1/coredns_1.10.1_linux_amd64.tgz
tar xzf coredns_1.10.1_linux_amd64.tgz
sudo mv coredns /usr/local/bin/

Now, create a configuration file for CoreDNS:

sudo mkdir /etc/coredns
sudo nano /etc/coredns/Corefile

Add the following content to the Corefile:

.:53 {
    hosts {
        192.168.1.10 server.local
        192.168.1.20 client1.local
        192.168.1.30 client2.local
        fallthrough
    }
    forward . 1.1.1.1
    log
    errors
}

Replace the IP addresses with your actual VM IP addresses.

Create a systemd service file for CoreDNS:

sudo nano /etc/systemd/system/coredns.service

Add the following content:

[Unit]
Description=CoreDNS DNS server
After=network.target

[Service]
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
Restart=on-failure

[Install]
WantedBy=multi-user.target

Start and enable the CoreDNS service:

sudo systemctl daemon-reload
sudo systemctl start coredns
sudo systemctl enable coredns
  1. Configure two client VMs:

On each client VM, edit the /etc/resolv.conf file to use the CoreDNS server as the primary DNS:

sudo nano /etc/resolv.conf

Add the following content (replace 192.168.1.10 with your CoreDNS server's IP):

nameserver 192.168.1.10
nameserver 1.1.1.1
  1. Configure CoreDNS for local resolution and fallback to 1.1.1.1:

This is already done in the Corefile we created earlier. The hosts plugin handles local resolution, and the forward plugin sends unresolved queries to 1.1.1.1.

  1. Set up SSL for hostname.local:

To set up SSL for hostname.local, you'll need to use a tool like certbot to generate SSL certificates. However, since ".local" is not a valid public top-level domain, you won't be able to get a publicly trusted certificate for it.

Instead, you can create a self-signed certificate:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/hostname.local.key -out /etc/ssl/certs/hostname.local.crt

Follow the prompts, ensuring you set the Common Name to "hostname.local".

Now you can use these certificates in your web server configuration (e.g., Apache or Nginx) to enable HTTPS for hostname.local.

Remember that clients will need to add an exception for this self-signed certificate, as it won't be trusted by default.

This setup should allow you to resolve local hostnames using CoreDNS, fall back to 1.1.1.1 for internet queries, and use a self-signed SSL certificate for hostname.local. Keep in mind that for production environments, it's generally better to use a proper domain name and obtain a certificate from a trusted Certificate Authority.

@anubhavg-icpl
Copy link
Author

It looks like the CoreDNS service is failing to start. The error suggests there might be an issue with the executable file or its permissions. Let's troubleshoot this step by step:

  1. First, let's check if the CoreDNS binary is in the correct location and has the right permissions:
ls -l /usr/local/bin/coredns

Make sure the file exists and has execute permissions. If it doesn't, you can set them with:

sudo chmod +x /usr/local/bin/coredns
  1. Next, let's verify the content of the Corefile:
cat /etc/coredns/Corefile

Ensure it matches what we set up earlier.

  1. Let's try running CoreDNS manually to see if there are any error messages:
sudo /usr/local/bin/coredns -conf /etc/coredns/Corefile

This should give us more detailed error information if there's a problem with the configuration.

  1. Check the system logs for more details:
sudo journalctl -u coredns.service

This will show us the logs specific to the CoreDNS service.

  1. Make sure SELinux is not blocking the execution. You can temporarily disable SELinux to test:
sudo setenforce 0
sudo systemctl restart coredns

If this works, you'll need to create proper SELinux policies instead of keeping it disabled.

  1. Verify that the ports CoreDNS is trying to use (typically 53) are not already in use:
sudo lsof -i :53

If another service is using port 53, you'll need to stop that service or configure CoreDNS to use a different port.

  1. Check if there are any firewall rules blocking CoreDNS:
sudo firewall-cmd --list-all

You may need to add a rule to allow DNS traffic:

sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload

After trying these steps, attempt to start the service again:

sudo systemctl start coredns
sudo systemctl status coredns

If you're still encountering issues, please provide the output of steps 1, 3, and 4 from above. This will give us more information to diagnose the problem.

@anubhavg-icpl
Copy link
Author

SELinux and CoreDNS: Understanding the Interaction

What is SELinux?

SELinux (Security-Enhanced Linux) is a security mechanism implemented in the Linux kernel. It provides an additional layer of system security to complement traditional Unix discretionary access controls. SELinux operates on the principle of least privilege, where processes are granted only the permissions they need to function.

Why Disable SELinux for CoreDNS?

The command sudo setenforce 0 temporarily sets SELinux to permissive mode. This is suggested as a troubleshooting step for CoreDNS for several reasons:

  1. Default Policies: SELinux's default policies might not accommodate CoreDNS's specific requirements, especially if CoreDNS was manually installed rather than through the system's package manager.

  2. File Contexts: CoreDNS may need to access files or directories that SELinux is preventing it from reaching due to incorrect file contexts.

  3. Network Access: SELinux might be blocking CoreDNS from binding to certain ports or accessing network resources it needs to function.

  4. Diagnosis: By temporarily disabling SELinux, you can determine if it's the cause of CoreDNS's startup issues. If CoreDNS starts successfully with SELinux in permissive mode, you know that SELinux policies are the root cause.

The Proper Solution

While sudo setenforce 0 is a quick way to diagnose if SELinux is causing issues, it's not a long-term solution. Instead:

  1. Check SELinux Logs: Look for denied actions in /var/log/audit/audit.log.

  2. Use SELinux Troubleshooting Tools: Tools like audit2allow can help generate the necessary SELinux policies.

  3. Create Custom SELinux Policies: Based on the audit logs, create custom policies that allow CoreDNS to perform its required actions while maintaining overall system security.

  4. Set Correct File Contexts: Use semanage fcontext and restorecon to set and apply the correct SELinux context to CoreDNS files and directories.

Example of Creating a Custom Policy

If you find that SELinux is blocking CoreDNS, you might create a custom policy like this:

# Generate a custom policy module
ausearch -c 'coredns' --raw | audit2allow -M my-coredns

# Apply the custom policy
semodule -i my-coredns.pp

This creates and applies a custom SELinux policy module that allows CoreDNS to perform the actions that were previously blocked.

Remember, while temporarily disabling SELinux can help in diagnosis, properly configuring SELinux to work with CoreDNS is the secure and recommended approach for production environments.

@anubhavg-icpl
Copy link
Author

Implementing Custom SELinux Policy for CoreDNS

Step 1: Ensure SELinux is Enabled

First, make sure SELinux is in enforcing mode:

sudo setenforce 1

Step 2: Start CoreDNS and Generate Audit Logs

Start CoreDNS and let it run for a while to generate SELinux audit logs:

sudo systemctl start coredns

If CoreDNS fails to start, that's okay. We'll use the generated audit logs to create our policy.

Step 3: Analyze SELinux Audit Logs

Use the ausearch command to find CoreDNS-related SELinux denials:

sudo ausearch -c 'coredns' --raw

Step 4: Generate a Custom SELinux Policy Module

Use audit2allow to generate a custom policy based on the audit logs:

sudo ausearch -c 'coredns' --raw | audit2allow -M my-coredns

This command creates two files: my-coredns.te (Type Enforcement file) and my-coredns.pp (compiled policy package).

Step 5: Review the Generated Policy

Examine the contents of my-coredns.te:

cat my-coredns.te

Review the rules to ensure they make sense for CoreDNS operations. You may need to manually adjust this file if there are overly permissive rules.

Step 6: Apply the Custom Policy

Apply the new policy module:

sudo semodule -i my-coredns.pp

Step 7: Set Correct File Contexts

Ensure CoreDNS files have the correct SELinux context:

sudo semanage fcontext -a -t bin_t "/usr/local/bin/coredns"
sudo restorecon -v /usr/local/bin/coredns

sudo semanage fcontext -a -t etc_t "/etc/coredns(/.*)?"
sudo restorecon -R -v /etc/coredns

Step 8: Configure SELinux Boolean for Network Access

Allow CoreDNS to access the network:

sudo setsebool -P named_bind_http_port 1

Step 9: Restart CoreDNS

Restart the CoreDNS service:

sudo systemctl restart coredns

Step 10: Verify CoreDNS is Running

Check the status of CoreDNS:

sudo systemctl status coredns

If CoreDNS is running successfully, your SELinux policy is working correctly.

Step 11: Monitor for Further SELinux Denials

Continue to monitor SELinux logs for any new denials:

sudo ausearch -c 'coredns' --raw

If you see new denials, repeat steps 4-7 to refine your policy.

Troubleshooting

If you encounter issues:

  1. Check CoreDNS logs: sudo journalctl -u coredns
  2. Review SELinux logs: sudo cat /var/log/audit/audit.log | grep coredns
  3. Temporarily set SELinux to permissive mode to isolate SELinux-related issues: sudo setenforce 0

Remember to set it back to enforcing mode (sudo setenforce 1) after troubleshooting.

By following these steps, you've created a custom SELinux policy that allows CoreDNS to function properly while maintaining the security benefits of SELinux.

@anubhavg-icpl
Copy link
Author

CoreDNS Setup for Local Network with SSL and Custom SELinux Policy

Table of Contents

  1. Introduction
  2. System Architecture
  3. Prerequisites
  4. Installation
  5. Configuration
  6. SELinux Configuration
  7. SSL Configuration
  8. Troubleshooting
  9. Advanced Usage
  10. Contributing
  11. License

Introduction

This project sets up a local DNS infrastructure using CoreDNS, with one Debian server acting as the DNS server and two client VMs. The system is designed to use CoreDNS for local hostname resolution and fall back to 1.1.1.1 for internet queries. Additionally, it includes SSL configuration for secure local connections and a custom SELinux policy for enhanced security.

[Sections 2-5 remain the same as in the previous version]

SELinux Configuration

To ensure CoreDNS functions correctly with SELinux enabled, follow these steps to create and apply a custom SELinux policy:

  1. Ensure SELinux is in enforcing mode:

    sudo setenforce 1
  2. Start CoreDNS to generate audit logs:

    sudo systemctl start coredns
  3. Analyze SELinux audit logs:

    sudo ausearch -c 'coredns' --raw
  4. Generate a custom SELinux policy module:

    sudo ausearch -c 'coredns' --raw | audit2allow -M my-coredns
  5. Review the generated policy:

    cat my-coredns.te
  6. Apply the custom policy:

    sudo semodule -i my-coredns.pp
  7. Set correct file contexts:

    sudo semanage fcontext -a -t bin_t "/usr/local/bin/coredns"
    sudo restorecon -v /usr/local/bin/coredns
    sudo semanage fcontext -a -t etc_t "/etc/coredns(/.*)?"
    sudo restorecon -R -v /etc/coredns
  8. Configure SELinux boolean for network access:

    sudo setsebool -P named_bind_http_port 1
  9. Restart CoreDNS:

    sudo systemctl restart coredns
  10. Verify CoreDNS is running:

    sudo systemctl status coredns
  11. Monitor for further SELinux denials:

    sudo ausearch -c 'coredns' --raw

[Sections for SSL Configuration, Troubleshooting, Advanced Usage, Contributing, and License remain the same as in the previous version]

@anubhavg-icpl
Copy link
Author

image

@mranv
Copy link

mranv commented Sep 21, 2024

I understand that you're experiencing an issue where the DNS settings in /etc/resolv.conf on your client VMs are changing automatically from your CoreDNS server IP (192.168.122.16) to another IP (192.168.122.1). This is a common issue in many Linux distributions, especially those using NetworkManager or systemd-resolved.

To prevent this from happening and to make your DNS settings persistent, you can try the following solutions:

  1. Use DHCP client configuration:

Edit the DHCP client configuration file:

sudo nano /etc/dhcp/dhclient.conf

Add these lines at the end of the file:

supersede domain-name-servers 192.168.122.16;
prepend domain-name-servers 192.168.122.16;

Replace 192.168.122.16 with your CoreDNS server IP.

  1. Configure NetworkManager:

If you're using NetworkManager, you can configure it to use a specific DNS server:

sudo nmcli connection modify <connection-name> ipv4.dns "192.168.122.16"
sudo nmcli connection modify <connection-name> ipv4.ignore-auto-dns yes

Replace with your actual connection name (you can find it using nmcli connection show).

  1. Configure systemd-resolved:

If your system uses systemd-resolved, you can configure it to use your CoreDNS server:

sudo nano /etc/systemd/resolved.conf

Add or modify these lines:

DNS=192.168.122.16
DNSStubListener=no

Then restart the service:

sudo systemctl restart systemd-resolved
  1. Make /etc/resolv.conf immutable:

As a last resort, you can make the /etc/resolv.conf file immutable:

sudo chattr +i /etc/resolv.conf

This prevents any process from modifying the file. However, be cautious with this method as it might interfere with some system processes.

  1. Use resolvconf:

Install resolvconf:

sudo apt-get install resolvconf

Then edit /etc/resolvconf/resolv.conf.d/head:

sudo nano /etc/resolvconf/resolv.conf.d/head

Add your nameserver:

nameserver 192.168.122.16

Update resolvconf:

sudo resolvconf -u

Choose the method that best fits your system configuration. After applying these changes, your DNS settings should persist and continue to use your CoreDNS server (192.168.122.16) as the primary DNS.

Remember to replace 192.168.122.16 with your actual CoreDNS server IP in all these examples.

@mranv
Copy link

mranv commented Sep 21, 2024

the above issue can help to resolve the recent removeal of nameserver from the /etc/resolve.conf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment