Tag: ubuntu

Implementing Per-Domain DNS Configuration on Linux Ubuntu Using dnsmasq

Reading time: 41 – 68 minutes

In Linux, managing network traffic is essential for a robust and secure IT infrastructure. In this post, we focus on Ubuntu—whether running on a virtual machine, Windows Subsystem for Linux (WSL), or a physical machine running Ubuntu 24.04. We will configure per-domain DNS rules using dnsmasq. This guide also covers additional considerations for WSL and systems using netplan.

Configuring Ubuntu for Local DNS with dnsmasq

When using Ubuntu, you might be using netplan for network configuration. In that case, you need to configure netplan to use the local DNS server provided by dnsmasq. Make sure your netplan configuration (e.g., /etc/netplan/01-netcfg.yaml) sets the DNS to 127.0.0.1, so that all DNS queries are forwarded to your local dnsmasq server.

Disabling systemd-resolved

Ubuntu often uses systemd-resolved by default, which can interfere with your custom DNS setup. To prevent conflicts, disable and stop systemd-resolved using the following commands:

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
sudo systemctl daemon-reload

This ensures that systemd-resolved does not override your DNS settings.

Note for WSL Users

If you are running Ubuntu under WSL, you need to prevent WSL from overwriting your DNS settings. Edit or create the file /etc/wsl.conf with the following content:

[network]
generateResolvConf = false

Then, create or edit the /etc/resolv.conf file to include:

nameserver 127.0.0.1

This ensures that your system uses the local dnsmasq server.

Installing and Setting Up dnsmasq

Step 1: Install dnsmasq

First, update your package list and install dnsmasq:

sudo apt update
sudo apt install dnsmasq

Step 2: Enable and Verify the dnsmasq Service

After installing dnsmasq, enable the service and check its status to ensure it is running correctly:

sudo systemctl enable dnsmasq
sudo systemctl daemon-reload
sudo systemctl start dnsmasq
sudo systemctl status dnsmasq

You should see that dnsmasq is active and running. This local DNS server will be used to resolve all DNS queries forwarded from your system.

Step 3: Configure dnsmasq

Edit the /etc/dnsmasq.conf file to set up your DNS rules. Here’s an example configuration:

# Default upstream DNS servers
server=8.8.8.8
server=8.8.4.4

# Domain-specific DNS servers
server=/domain01.tld/172.30.0.1
server=/domain02.tld/172.30.0.2

Explanation:

  • The lines server=8.8.8.8 and server=8.8.4.4 set Google’s public DNS as the default upstream DNS servers. When a query does not match any domain-specific rule, dnsmasq will forward the request to these servers.
  • The lines server=/domain01.tld/172.30.0.1 and server=/domain02.tld/172.30.0.2 specify that queries for any host within domain01.tld and domain02.tld should be resolved by the DNS servers at 172.30.0.1 and 172.30.0.2, respectively.

After making your changes, save the file and restart dnsmasq to apply the new configuration:

sudo systemctl restart dnsmasq

Verifying the DNS Configuration

You can use the dig command to verify that your DNS rules are working as expected. Note that when your system’s resolver is set to use dnsmasq at 127.0.0.1, the dig output will always show SERVER: 127.0.0.1#53. However, dnsmasq will forward the query internally to the appropriate upstream DNS server based on your configuration.

Below are two examples: one for a public domain (google.com) and one for a domain that should be resolved by your custom DNS rule (example01.tld).

Example 1: Verifying a Public Domain (google.com)

Run the following command:

dig google.com

Simulated Output:

; <<>> DiG 9.11.3-1ubuntu1-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;google.com.                    IN      A
;; ANSWER SECTION:
google.com.             300     IN      A       172.217.164.110
google.com.             300     IN      A       172.217.164.78
;; Query time: 23 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 20 10:00:00 UTC 2025
;; MSG SIZE  rcvd: 113

Internal Process:

  • Step 1: The query for google.com is sent to the local dnsmasq server at 127.0.0.1.
  • Step 2: dnsmasq examines its configuration and sees that google.com does not match any domain-specific rules.
  • Step 3: It then forwards the query to the default upstream DNS servers (8.8.8.8 and 8.8.4.4).
  • Step 4: The upstream server resolves google.com and returns the result back to dnsmasq, which then passes it back to the client.

Example 2: Verifying a Domain with a Custom DNS Rule (example01.tld)

Run the following command:

dig example01.tld

Simulated Output:

; <<>> DiG 9.11.3-1ubuntu1-Ubuntu <<>> example01.tld
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 67890
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;example01.tld.               IN      A
;; ANSWER SECTION:
example01.tld.           60      IN      A       172.30.0.1
;; Query time: 25 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 20 10:00:10 UTC 2025
;; MSG SIZE  rcvd: 82

Internal Process:

  • Step 1: The query for example01.tld is sent to dnsmasq at 127.0.0.1.
  • Step 2: dnsmasq checks its configuration and finds a matching domain-specific rule for example01.tld, which directs the query to the DNS server at 172.30.0.1.
  • Step 3: dnsmasq forwards the query internally to 172.30.0.1 without exposing this step in the client’s dig output.
  • Step 4: The upstream server at 172.30.0.1 resolves the query, and dnsmasq returns the answer to the client.

In both cases, while the client sees the query being handled by 127.0.0.1, dnsmasq intelligently directs the queries to the appropriate upstream servers based on your configuration. This seamless internal forwarding is what allows you to manage per-domain DNS resolution effectively.

Conclusion: Why Use Per-Domain DNS Configuration?

Implementing per-domain DNS configuration on Linux Ubuntu is a powerful way to gain granular control over your network’s behavior. This approach is particularly useful for:

  • Enterprise Environments: Where internal domains require different DNS resolutions from external queries.
  • Development and Testing: Allowing developers to redirect domain requests to local or test servers.
  • Security: Enhancing network security by segregating traffic and reducing reliance on external DNS servers.

By configuring dnsmasq with domain-specific rules and ensuring that your system points to the local DNS (especially important when using netplan or running under WSL), you optimize network performance and security tailored to your specific needs.

Deploying gotop with Ansible

Reading time: 5 – 8 minutes

Gotop is a terminal based graphical activity monitor inspired by gtop and vtop; it’s available at:

https://github.com/xxxserxxx/gotop/

I published a role in Ansible Galaxy for deploying gotop in Linux servers. The role page in Ansible Galaxy is at:

https://galaxy.ansible.com/oriolrius/install_gotop

Role installation command and deployment command:

ansible-galaxy install oriolrius.install_gotop

# change SERVER_IP, for the IP address where you want to deploy gotop
ansible -i SERVER_IP, -u root -m include_role -a name=oriolrius.install_gotop all

Ubuntu synchronize NTP clock

Reading time: 2 – 4 minutes

Synchronise Linux clock when NTP service is running but the clock is not on time:

sudo service ntp stop
sudo ntpd -gq
sudo service ntp start

Upgrading Redmine in a nutshell

Reading time: 14 – 23 minutes

I use Redmine to track my personal projects, and every time that I have to update I have to re-read the full upgrading page which is long and full of exceptions. So I decided to write my own reduced cookbook to solve that. FYI I’m using Ubuntu 16.04, Apache2, MySQL and Passenger for running Redmine. 

Being root user run:

backup MySQL database

download new redmine package and unpack in /var/www

change ‘redmine’ soft link to new folder

copy old files and directories overwriting the new ones:<br><pre><code>config/database.yml<br>config/configuration.yml<br>files/<br>plugins/</code></pre><br>
locating work directory on new redmine folder, run:<br><pre>bundle install --without development test<br>bundle exec rake generate_secret_token<br>bundle exec rake db:migrate RAILS_ENV=production<br>bundle exec rake redmine:plugins:migrate RAILS_ENV=production<br>bundle exec rake tmp:cache:clear tmp:sessions:clear RAILS_ENV=production</pre><br>

restart apache server

Ubuntu server as wifi AP and Mikrotik as a DHCP server

Reading time: 18 – 29 minutes

It’s important to have a very clear picture about the scenario that we’re going to configure in that case because it’s a little bit particular. This is an evolution of the previous post: Ubuntu server as wifi AP and Mikrotik as a DHCP server

schema

There is a server running Ubuntu 16.04 and offering wifi service as an AP. The wifi interface is in bridge mode with the ethernet port and send all traffic to the Mikrotik gateway where there is a DHCP server in charge to serve IP address to wifi clients.

Start by configuring the bridge in the Ubuntu server. File “/etc/network/interfaces”:

source /etc/network/interfaces.d/*

auto lo br0
iface lo inet loopback

#ethernet interface
allow-hotplug enp2s0
iface enp2s0 inet manual

#wifi interface
allow-hotplug wlp3s0
iface wlp3s0 inet manual

# Setup bridge
iface br0 inet static
    bridge_ports enp2s0 
    address 192.168.2.2
    netmask 255.255.255.0
    network 192.168.2.0

Pay attention on “bridge_ports” the wifi interface is not added on the list, this is because until the hostapd is running it doesn’t make sense to do that. You’ll see “bridge=br0” option on hostapd.conf which will fix that misbehavior.

Wifi AP configuration, “/etc/default/hostapd”:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

and “/etc/hostapd/hostapd.conf”:

bridge=br0                # bridge interface
interface=wlp3s0          # wifi interface name
driver=nl80211
ssid=the_ssid_name        # name of your network
hw_mode=g
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=the_secret_key   # secret key to joing with the wifi network
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
logger_syslog=-1
logger_syslog_level=3
logger_stdout=-1
logger_stdout_level=1

DHCP server configuration on Mikrotik:

# setting the interface address, in my case ether4
/ip address
add address=192.168.2.1/24 interface=ether4 network=192.168.2.0

# setting up DHCP on interface 4 of the mikrotik device
/ip dhcp-server
add address-pool=dhcp-pool disabled=no interface=ether4 name=dhcp-pool

# network of the DHCP server
/ip dhcp-server network
add address=192.168.2.1.0/24 dns-server=8.8.8.8 domain=your_network.local gateway=192.168.2.1 netmask=24

# IP pool used by the DHCP server
/ip pool
add name=dhcp-pool ranges=192.168.2.65-192.168.2.70

Cookbook: set-up a TFTP server on Ubuntu

Reading time: 8 – 12 minutes

Sometimes TFTP is the only protocol available to exchange files with an embedded system. So, it’s very easy to have that supported in our workstation or any other place to exchange files with those systems.

Set up steps:

apt-get install tftpd-hpa

modify file “/etc/default/tftpd-hpa”:

TFTP_OPTIONS="--secure --create"

–secure: Change root directory on startup. This means the remote host does not need to pass along the directory as part of the transfer, and may add security. When –secure is specified, exactly one directory should be specified on the command line. The use of this option is recommended for security as well as compatibility with some boot ROMs which cannot be easily made to include a directory name in its request.

–create Allow new files to be created. By default, tftpd will only allow upload of files that already exist. Files are created with default permissions allowing anyone to read or write them, unless the –permissive or –umask options are specified.

Needed to allow uploads in that directory:

chown -R tftp /var/lib/tftpboot

Restart and check if the service is running:

service tftpd-hpa restart
service tftpd-hpa status
netstat -a | grep tftp

Remove old kernels when there is no space in /boot

Reading time: 8 – 14 minutes

The first step is get some space in the partition “/boot” because without that it’s impossible to do anything.

So go to /boot and remove some “initrd” files as they are the biggest ones. A few of them will be enough.

After that a good point is to ensure there is no partial installation pending to finish:

apt-get -f install

Now it’s a good idea to purge all kernels except the running one:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

To avoid that in future before filling the partition, it’s a good idea to install and run periodically: purge-old-kernels. Installation and example of use are:

# installation
apt-get install bikeshed
# keep three old kernels:
purge-old-kernels --keep 3
# if you want to put that in the crontab use that command
purge-old-kernels --keep 3 -qy

If you’re a Grub user don’t forget to run:

update-grub2

Personally I have a nightmare with that problem and Ubuntu, especially with version 12.04 which is installed in a lot of servers that I manage. I repeated the previous process a lot of times and in the end, I decided to document it because I always have to go to Google and find the proper steps to solve that problem.

Relay mail from your server without MTA

Reading time: < 1 minute Sometime you need to send notifications or simply you need to use sendmail command from your server, but you don't want to use a local mail server. Maybe use simple SMTP (ssmtp) could be a good idea to solve this kind of situations. I use to configure SSMTP with a GMail account to send notifications from server different daemons, for example, crontab, supervisord, etc. This is a cookbook configuration for SSMTP and GMail: /etc/ssmtp/ssmtp.conf
root=user@gmail.com
mailhub=smtp.gmail.com:587
rewriteDomain=
hostname=user@gmail.com
UseSTARTTLS=YES
AuthUser=user@gmail.com
AuthPass=password
FromLineOverride=YES

/etc/ssmtp/revaliases

root:username@gmail.com:smtp.gmail.com:587
localusername:username@gmail.com:smtp.gmail.com:587

Installation in ubuntu server is as easy as: apt-get install ssmtp

Changing Ubuntu CLI language

Reading time: 2 – 4 minutes

My mother tongue is Catalan and of course I speak and understand Spanish very well, but when I’m using a Linux CLI it’s impossible to be agile if the interface is not in English. Then when I need to change Ubuntu interface to English I modify the file /etc/default/locale: 

LANG=en_US.UTF-8
LANGUAGE="en_US:en"
Scroll to Top