0. Overview of Lab 4 :
Welcome to 4th lab. Here the short action list we will do in this lab:
- Verifying previous lab tasks
- Installing updates
- Performing backup
- Configuring firewall (understanding iptables tables and chains)
- Installing Domain Name Server
- Configuring own local resolver server (allowing recursion and caching)
- Configuring own domain zone, understanding world and local resolvers
- Configuring forwarding, understanding domain injection <- maybe next time
1.Make sure you did finish all the tasks of the previous week.
PS! Before continuing please make sure you have completed all previous labs.
- Access to ETAIS was granted and you can login with your UT credentials.
- VM was created and is visible in the list of VMs in ETAIS
- VM has Internal and External IP addresses
- VM is reachable on External IP (from UT eduroam Wi-Fi, class 123 Wi-Fi or UT VPN)
- VM has
SSH
service running and you can login into VM using SSH private key - VM has tester account created, tester can login using his SSH private key
- User
tester
can execute a commandsudo ls -lhtr /root
without any error or prompt for password
Additionally - Securing your ssh server
One thing that makes ssh server more secure is disabling password authentication. We disable it since we use our private key to log in and we disable password login, because people often use bad (easy to quess) passwords. We want to elminate that risk and since we use key, we disable it.
- Open and edit the file
/etc/ssh/sshd_config
- Change the value of
PasswordAuthentication
to no.
- Change the value of
2. Check for the updates using debian package manager
We have worked with package manager apt
during Lab1 (installing the system). Moreover, in the Lab3 we did upgrade packages, therefore the exact commands we expect you to know.
- Update the package index
- Check if any updates are available
- Perform the upgrade if needed
- Reboot the VM in case Linux Kernel or Initial RAM-fs was upgraded
- This will be visible from the upgrade logs
- Alternatively you can list the /boot directory to check if any files were updated recently
- Consider the
ls
command, please have a look at options-l
,-t
,-r
and-h
(those might be helpful to produce detailed, time-ordered output)
- Consider the
We can count the system up-to-date if there is no more updates suggested by the package manager
- In case you performed reboot, make sure the VM booted and is back on-line and you can ssh into it
After upgrading the system it wise to clean the left-overs: the downloaded deb packages. Moreover it is wise to remove the packages that are not used anymore. The are two commands responsible for performing these actions:
# Remove the downloaded packages apt autoclean # Uninstall the not used packages apt autoremove
Perform the cleaning and remove not used packages
3. Perform backup
We are about to introduce some portion of changes to our system during this lab therefore it is wise to backup the current state first. Pay attention that one of the changes we do is the Firewall
configurations, mistake in iptables
syntax or wrong order of the rules in iptables chains
might result in locking the network access (deny-all rule). Once network access is lost - you can't control your VM anymore over SSH. There is no recovery console (no VNC access allowed this year) - VM will be considered lost once inaccessible from the network. The ETAIS infrastructure does allows to perform the snapshots of the hard-drives. By doing the snapshot you literally saving the state of the whole hard drive up to date. Once the snapshot is done you can proceed with dangerous actions knowing that you can always recover in case you mis-configure something.
In ETAIS interface issue the snapshot of the hard-drive
- ETAIS -> Resources -> VM -> Backup Tab -> Create
4. Configure the firewall
<TODO: packet filter tables and chains explanations>
Change to root shell, make sure iptables command is present.
# iptables
If the output is iptables v1.x.x: no command specified then iptables is present.
Check existing tables filter and nat, use the -S
option to print the rules, use -t
option with nat parameter to alternate the table (default one is always filter table).
# iptables -S
# iptables -t nat -S
By the default both tables should be clean, and the default policy set to ACCEPT.
Example output:
root@myvm:~# iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT root@t72:~# iptables -t nat -S -P PREROUTING ACCEPT -P INPUT ACCEPT -P OUTPUT ACCEPT -P POSTROUTING ACCEPT
Now add the following rules to you iptables:
- Allow receiving everything on loopback interface
# iptables -A INPUT -i lo -j ACCEPT
- Allow receiving replies for established connections (*) as well as for related ones (*)
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
- Allow receiving everything of the ICMP protocol
# iptables -A INPUT -p icmp -j ACCEPT
- Allow receiving new connections on TCP port 22 (SSH service)
# iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
- Prepare to reject, log the packet before rejecting (not often then 50 packets per minute)
# iptables -A INPUT -m limit --limit 50/min -j LOG --log-prefix "Firewall denied 50/m:"
- Gracefully reject the packet with ICMP reply
# iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
Now whenever your machine receives a packet it is automatically checked against the iptables' rules (table filter, chain INPUT). If the incoming packet corresponds to any of the rules the packet is accepted. Otherwise the iptables' checking reaches the final rule -A INPUT -j REJECT which gracefully rejects the incoming packet and no replying the source host with ICMP message Port unreachable.
We did introduce those rules in a dangerous manner, as our remote shell (SSH connection) may be a subject of the rules we applied. In case we did not loose connection to our VM after applying the rules, we may conclude we have done everything right.
<TODO: add host-to-vm firewall testing commands using netcat>
- Save the current
iptables
rules into a file:# iptables-save > /etc/firewall.conf
- Make sure the same rules that were save are also in the current iptables:
# iptables-restore < /etc/firewall.conf
- Write iptables-restore < /etc/firewall.conf into /etc/network/if-up.d/iptables file:
# echo "iptables-restore < /etc/firewall.conf" > /etc/network/if-up.d/iptables
- Open the file up for editing:
# nano /etc/network/if-up.d/iptables
- Add the following line to the first line of the file:
- #!/bin/bash
- Change the rules for using the file:
# chmod a+x /etc/network/if-up.d/iptables
5. Disable IPv6
The ETAIS cloud does not suggest any IPv6 network providers, therefore is is pointless to keep the IPv6 stack up in our VMs. In this section we are going to disable the IPv6 stack by alternating kernel runtime parameters.
System wide configuration variables are managed using sysctl
utility. Example:
- To print the whole list of system settings use:
- # sysctl -A
- To see specific variable value:
- # sysctl variableName
- To set a specific variable to a new value use:
- # sysctl <variable>=<value>
This will however change only running system setting and will reset to default values after system restart. In order to alter the default values put the corresponding variables in the end of /etc/sysctl.conf
file, example content of /etc/sysctl.conf
(only few last lines shown):
...
# My default value of aa.bb.cc_var1 variable
aa.bb.cc_var1=1
...
During this Lab we do not configure any service to rely on IPv6 hence we do not need the system wide IPv6 stack. Let's disable it using well studied sysctl
utility.
Disable the use of IPv6:
- Check the value of the following variables:
-
net.ipv6.conf.default.disable_ipv6
-
net.ipv6.conf.all.disable_ipv6
-
- Change current system config using
sysctl
command, set the value of both variables to1
- Open the
/etc/sysctl.conf
, check if these variables exist (most likely there is no such lines and you need to add them to the end of the file. Save and close file.
Afterwards enter
sysctl -p /etc/sysctl.conf
Now if you check your network interfaces using ip addr l
command, there should be no inet6
prefixed lines.
- $ ip addr l
And if you still see inet6
lines in the output, there is something you may have missed in the previous manual.
6. Domain Name System (DNS) using BIND software
DNS (Domain Name Service) is the main name service used in the Internet. Name services are used to translate names meaningful to humans into the numerical/binary addresses/numbers (and vice versa). Practically every system relies on a working name service. The name service has not always to be set up in-house, most often it is provided by the Internet Service Provider (ISP).
Extra materials
- Wikipedia: Domain Name System
- DNS for Rocket Scientists
- BIND 9 Administrator Reference Manual
- Just a Good BIND9 Manual
Domain Hierarchy for System Administration Labs
For our practicals we will use our own domain hierarchy starting from the top level domains. DNS management is based on strict delegation, so we are unable to introduce our "fake" top level domains into the "real" DNS system used in the Internet. That is why our top level domains will only work on the lab systems.
The domain hierarchy is divided into zones based on authority:
- The authority over root domain and top level domains will belong to the teaching staff. 2018 we will be using top level domain .est From now on this will be marked by
.est
- Every participant/system will have authority over a second-level domain
ut_login.est
, under which one or more names may be defined. "ut_login" refers to your official University of Tartu login name, that you will be using in order to access https://ois.ut.ee page for example. It is mandatory to have a name for every host/sub system in the lab group under each of these second-level domains. The general form for these names is <host>.ut_login.est
Here "<host>" refers the host name of your VM that was chosen chosen during VM setup dialog in ETAIS web interface. You can always check the host name of your VM by calling hostname
command and cat /etc/hostname
command.
For example:
- If student John Doe has his UT login john81 and his VM was named johnvm then full hostname is johnvm.john81.est
Changing hostname
By default all the debian instances are set by ETAIS during VM setup as a host name. During this lab we are going to setup a personal DNS server (serving personal donmain <ut_login>.est). Our VM will join the domain by name <host>.<ut_login>.est. Therefore next we prepare VM by alternating its host name from short notation to full qualified domain notation, Example for johnvm in john81.est domain:
* short notation: johnvm * fqdn notation: johnvm.john81.est
To check your current host name consider command hostname
...
$ hostname
... and its output is exactly the host name in short notation: myhost
The host name is held in file /etc/hostname
, by altering the single line in this file you will alter the name of your host.
In addition there is a /etc/hosts
file, which provides fixed host name
<-> ip address
mappings, and has the following content (only lines we are interested in are shown):
...
- 127.0.0.1 localhost
- 127.0.1.1 myhost.novalocal myhost
...
The shown mappings allows local resolving of host names to IP address (without any requests to external services like DNS). This especially critical when testing your services locally, if you consider the simple command, like:
- $ ping localhost
... this will actually resolvelocalhost
to 127.0.0.1 using/etc/hosts
file.
There is another line in /etc/hosts
associating your current hostname to 127.0.1.1, in case we change our domain we need to modify this line. Example:
- my short host name is
myhost
, and my new domain isnewdom.xyz
, so the full domain namemyhost.newdom.xyz
- the line in
/etc/hosts
should rewritten as follows:- 127.0.1.1 newhost.newdom.xyz newhost
Now change your host name as described above, using pattern <host>.<ut_login>.est
for the new value. You can do it by editing files:
- /etc/hostname
- Add your full hostname <host>.<ut_login>.est
- <host> - your current hostname in short notation ( a result of
hostname
command) - <ut_login> - your university (UT) login
- <host> - your current hostname in short notation ( a result of
- Add your full hostname <host>.<ut_login>.est
- /etc/hosts
- Find the line
- 127.0.1.1 myhost.novalocal myhost
- Rewrite it into new values using your FDQN name (<host>.<ut_login>.est) and short name (<host>)
- Pay attention to the
warning
saying this file is automatically overwritten by system - Make a change in
/etc/cloud/cloud.cfg
as recommended byhosts
file so that cloud system does not overwrite it.
- Find the line
NOW reboot your instance to apply changes
- The logon screen must display the same hostname
- When logged in, use the following command to display the hostname:
$ hostname
- It should report you hostname in FQDN (<host>.<ut_login>.est)
- Try to ping yourself using your new hostname
7. Configuring the BIND Name Server
First install the Bind 9
DNS server related packages.
Install packages:
bind9
bind9utils
bind9-doc
dnsutils
As the BIND name server runs with the rights of the bind
user and group (not root
), you should always make sure that the main configuration file and zone files have the correct permissions and group ownership. Every file to be read by the BIND DNS server must be readable by bind
group. If you get "permission denied" errors, use the following commands to set the owner or group ownership, example:
# chgrp bind /etc/bind/targetConfFile.conf
# chown bind folder/file
and following commands to set the correct permissions: (Learn More)
# chmod 640 /etc/bind/targetConfFile.conf
- Will set rights rw- r-- ---
# chmod g+rX /etc/bind/targetConfFile.conf
- Will just set read right for the group
- Check lab0 manual for help with permissions. Use chown and chgrp to change owner/group. Use ls -la to check permissions/owner/group.
The main configuration file for BIND is spread across multiple files:
/etc/bind/named.conf
Main configuration file/etc/bind/named.conf.local
Local zone declarations/etc/bind/named.conf.options
Bind service options
The named.conf
file is the main one, which includes all the others and which is loaded by the bind9 server.
The named.conf.local
describes the local views or zone definitions (the zones that this name server knows about).
The named.conf.local.options
overall behavior of the name server. The contents of the zones (resource records) will be located in the /etc/bind/zones
directory, which we create later.
We are going to add another one called named.conf.logging
which will contain logging configurations and will make bind
write it's logs into files we have just created in previous task.
- Create file
named.conf.logging
into/etc/bind
usetouch
command. - Change the owner and the group of the newly created file, both to bind, use
chown
andchgrp
commands. - Edit the
named.conf
file and add the include statement pointing tonamed.conf.logging
.- Put this include statement before the line pointing to local and after one pointing to options.
From now on, the main configuration files are referred to as:
named.conf
- main filenamed.conf.local
- local definitionsnamed.conf.options
- options filenamed.conf.logging
- logging options
Add the logging configuration to the logging options file:
logging { channel update_debug { file "/var/log/bind9/update_debug.log" versions 3 size 100k; severity debug; print-severity yes; print-time yes; }; channel security_info { file "/var/log/bind9/security_info.log" versions 1 size 100k; severity info; print-severity yes; print-time yes; }; channel bind_log { file "/var/log/bind9/bind.log" versions 3 size 1m; severity info; print-category yes; print-severity yes; print-time yes; }; category default { bind_log; }; category lame-servers { null; }; category update { update_debug; }; category update-security { update_debug; }; category security { security_info; }; };
Now we add the simple caching DNS configuration to our bind9
server. This in order to get rid of the forwarding the DNS resolv queries to 10.10.10.1. Having the caching DNS server running locally on the same host will to the trick. Instead of forwarding the queries to 10.10.10.1 we will use our own resolver on 127.0.0.1 which has recursive resolving (and also caching) enabled.
Edit the options file named.conf.options
:
Add the following section into beginning of options file:
acl goodclients{ 127.0.0.0/8; };
Now find the options { ... }
declaration in options file and make sure the following lines are there:
dnssec-validation auto; auth-nxdomain no; # conform to RFC1035 listen-on { 127.0.0.1; }; listen-on-v6 { none; }; recursion yes; allow-query { goodclients; };
Regarding the previous configuration we first of all declare our white list of clients allowed to send the resolve queries to our bind9
server by having 127.0.0.0/8
localhost subnet declaration in acl
section.
In the options
section we leave dnssec-validation
and auth-nxdomain
untouched allowing defeault DNS security options and RFC conformance. Next we disable bind9
from listening to the IPv6, as we to not use system wide anyway. In addition we limit the scope of IPv4 by putting bind9
listen on localhost
only (the default port is 53 UDP). Next we enable recursion and apply the white-list with 2 last options. The recursion is needed in order to let bind9
act as standard caching recursive resolver (like those assigned by DHCP or put manually in /etc/resolv.conf
).
- Example query "where is courses.cs.ut.ee" is then resolved as follows:
- "where is .ee"
- "where is ut.ee"
- "where is cs.ut.ee"
- "where is courses.cs.ut.ee"
- The often made queries are cached and answered explicitly
Now you can check your configuration using named-checkconf
utility
- # named-checkconf
No output means configuration is OK.
Start the name server (service bind9
):
# service bind9 start
(useservice bind9 stop
if you already started it before)
Now query the service status and if needed, check the log files (those we have created in the beginning.
# service bind9 status
# systemctl status bind9.service -l
# journalctl -xn
If everything works fine and no error is reported, you may check how your local resolver is performing:
$ dig @127.0.0.1 courses.cs.ut.ee
$ dig @127.0.0.1 www.google.com
It should answer with list of IP addresse for courses.cs.ut.ee like this:
; <<>> DiG 9.9.5-9+deb8u5-Debian <<>> @127.0.0.1 courses.cs.ut.ee ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8228 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 6 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;courses.cs.ut.ee. IN A ;; ANSWER SECTION: courses.cs.ut.ee. 4320 IN CNAME demeter.at.mt.ut.ee. demeter.at.mt.ut.ee. 86400 IN A 193.40.36.81 ;; AUTHORITY SECTION: ut.ee. 43199 IN NS ns.ut.ee. ut.ee. 43199 IN NS ns2.ut.ee. ut.ee. 43199 IN NS ns2.eenet.ee. ;; ADDITIONAL SECTION: ns.ut.ee. 10799 IN A 193.40.5.99 ns2.ut.ee. 10799 IN A 193.40.5.76 ns2.ut.ee. 10799 IN AAAA 2001:bb8:2002:500:216:3eff:fe65:ae6f ns2.eenet.ee. 43199 IN A 193.40.0.12 ns2.eenet.ee. 43199 IN AAAA 2001:bb8:2001::12 ;; Query time: 159 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Tue Mar 08 11:55:40 EET 2018 ;; MSG SIZE rcvd: 252
If you get answer like this for courses.cs.ut.ee then local resolver is performing well. You may want to enable it for auto-starting at the boot time:
Enable auto-starting the bind9
:
# update-rc.d bind9 enable
Modifying DHCP client configuration
In our current setup VM gets it's IP automatically assigned (internal address) by DHCP server which resides in cloud router. In addition to IP address the DHCP server provision VM with several other options. You can list those options by looking into /etc/dhcp/dhclient.conf
file and locating the request
option, by default it looks as follows:
request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers;
For example the options domain-name, domain-name-servers, domain-search will be used to auto-configure the /etc/resolv.conf
. The last one contains the information regarding the resolver address the OS should contact to resolve host names to IP addresses. By default it looks as follows:
domain openstacklocal search openstacklocal nameserver 8.8.8.8 nameserver 8.8.4.4
In previous steps we have configure a local resolver which resides inside our VM (listening on 127.0.0.1:53). It is configure with recursive queries enable and therefore can resolve any world addresses (try dig @127.0.0.1 google.com). Next we would like to rely on our local resolver in place of one provisioned by DHCP server. Therefore we need to disable some options of DHCP client first. Namely in /etc/dhcp/dhclient.conf
file and request
variable, the following options we need to exclude, in order to disable the automatic provisioning of DNS resolver:
domain-name, domain-name-servers, domain-search, host-name,
Additionally we may disable the IPv6 related options (as we are not using IPv6)
Edit /etc/dhcp/dhclient.conf
- Find the
request
variable- comment out the following options:
- domain-name
- domain-name-servers
- domain-search
- host-name,
- Optionally comment out IPv6 related options
- comment out the following options:
- Save the file
'''WARNING: be careful editing this file - you might be unable to get DHCP client working in case typos are left. This will result in not getting IP next time VM boots.
Now the /etc/resolv.conf
will be not anymore rewritten by DHCP client (next time we reboot) and stays static. So we can safely edit it to rely on your own local resolver for doing DNS queries by replacing the namesever variable value with 127.0.0.1
Edit /etc/resolv.conf
- Change
nameserver
option to 127.0.0.1- in case you have multiple - you should leave just one
- Change
domain
option to your personal domain <ut_login>.est - Change
search
option to your personal domain <ut_login>.est
'''Reboot the VM. After rebooting make sure the /etc/resolv.conf
is not modified (you should see your configuration there and not the one set by DHCP server).
Now your local resolver is used system wide, so you can test it by just pinging some hosts by name:
$ ping www.google.com
Should resolve www.google.com and start pinging it.