{"id":767,"date":"2021-09-06T14:23:16","date_gmt":"2021-09-06T12:23:16","guid":{"rendered":"https:\/\/www.gonscak.sk\/?p=767"},"modified":"2024-06-28T13:50:02","modified_gmt":"2024-06-28T11:50:02","slug":"how-to-create-a-router-from-centos-8-stream","status":"publish","type":"post","link":"https:\/\/www.gonscak.sk\/?p=767","title":{"rendered":"How to create a router from Centos 8 Stream"},"content":{"rendered":"\n<p>Today, I need to rebuild and create a new one linux router. It will work with many networks, there will be DHCP and DNS server as well. <\/p>\n\n\n\n<p>So, at first, we will secure our server on service: ssh. I assume, that you already have enabled firewalld and public zone, only for sshd service. And internal network with dhcp or anything else.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SSHD deamon<\/h2>\n\n\n\n<p>At first, we configure our ssh service to be secure. Edit ssh configuration file and adjust there variables:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/ssh\/sshd_config<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">Port 22\nProtocol 2\nPermitRootLogin no\nPubkeyAuthentication yes\nPermitEmptyPasswords no\nPasswordAuthentication no\nAllowUsers bob<\/pre>\n\n\n\n<p>Now, we create on our client machine (in my place Ubuntu desktop PC) a new rsa-key pair for ssh authentication.  You can set some passphrase, but it is you opinion. In quotas, there is a comment for there key pair.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh-keygen -t rsa -b 4096 -C \"bob@example.com\"\nmeans:\n-b bits. Number of bits in the key to create\n-t type. Specify type of key to create\n-C comment<\/pre>\n\n\n\n<p>When you had these key pairs generated (under ~\/.ssh\/) like: id_rsa and id_rsa_pub, you can adjust your server, for accepting these key pair. Now, you must authorize to your server by password (last time). <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh-copy-id bob@IP-OF-SERVER<\/pre>\n\n\n\n<p>If everything is OK, now you can restart your sshd service on server, to load new configurations:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl restart sshd.service<\/pre>\n\n\n\n<p>And we can test, that other users is NOT allowed, and there is a need for key authentication:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh Alice@192.168.1.2\n  Alice@192.168.1.2: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).\n<\/pre>\n\n\n\n<p>But Bob is allowed:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh bob@192.168.1.2\n   Last login: Tue Aug 31 14:47:13 2021 from...<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up public interface<\/h2>\n\n\n\n<p>We use nmcli (command-line tool for controlling NetworkManager) for watching out of our interfaces:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nmcli device status\nDEVICE  TYPE      STATE        CONNECTION \nens1   ethernet  connected    ens1       \nens2    ethernet  unmanaged    --         \nens3    ethernet  unmanaged    --         \nens4   ethernet  unmanaged    --         \nens5   ethernet  unmanaged    --         \nlo      loopback  unmanaged    -- <\/pre>\n\n\n\n<p>Unmanaged interfaces are edited here:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/NetworkManager\/conf.d\/99-unmanaged-devices.conf<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">[keyfile]\nunmanaged-devices=interface-name:ens2;interface-name:ens3;interface-name:ens4;interface-name:ens5<\/pre>\n\n\n\n<p>And our ens1 is in config below. UUID we can generate with command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">uuidgen ens1<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">cat \/etc\/sysconfig\/network-scripts\/ifcfg-ens1 \n#ens1 - Internal Subnet\nTYPE=Ethernet\nPROXY_METHOD=none\nBROWSER_ONLY=no\nBOOTPROTO=none\nDEFROUTE=no\nIPV4_FAILURE_FATAL=no\nIPV6_FAILURE_FATAL=no\nIPV6INIT=no\nNAME=ens1\nUUID=e765c8d4-f05e-43b2-96dc-71eef59a908a\nDEVICE=ens1\nONBOOT=yes\nIPADDR=192.168.1.2\nPREFIX=24\nGATEWAY=192.168.1.1\nDNS1=192.168.1.1<\/pre>\n\n\n\n<p>Now, we can configure our public interface. In our example, it will be interface ens2. So, we can copy our first network-script for interface ens2 and edit it. First, generate uuid for this interface. Then adjust your public IP numbers.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">uuidgen ens2\ncp \/etc\/sysconfig\/network-scripts\/ifcfg-ens1 \/etc\/sysconfig\/network-scripts\/ifcfg-ens2\nvim \/etc\/sysconfig\/network-scripts\/ifcfg-ens2\n\n----reboot----\n\nnmcli device status\nDEVICE  TYPE      STATE        CONNECTION \nens1   ethernet  connected    ens1       \nens2    ethernet  connected    ens2  <\/pre>\n\n\n\n<p>Now, after some time, we can see many ssh attacks to our system. We can make more things. One is, change the port for ssh daemon. Or I use fail2ban services, for ban IP, that try to hack our server. Like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Aug 31 13:50:45 r3 sshd[3551]: Invalid user support from 116.98.160.162 port 17306\nAug 31 13:50:48 r3 sshd[3553]: Invalid user geral from 116.98.160.162 port 17006\nAug 31 13:50:49 r3 sshd[3555]: Invalid user omega from 116.110.97.171 port 57344\nAug 31 13:50:51 r3 sshd[3557]: Invalid user matt from 116.98.160.162 port 49776\nAug 31 13:50:57 r3 sshd[3559]: Invalid user rebecca from 116.110.97.171 port 38964\nAug 31 13:51:02 r3 sshd[3561]: Invalid user admin from 171.240.203.115 port 32926\nAug 31 13:51:24 r3 sshd[3564]: Invalid user support from 116.110.97.171 port 49868\nAug 31 13:55:38 r3 sshd[3603]: Invalid user vasilias from 161.97.112.53 port 54654\nAug 31 13:55:42 r3 sshd[3605]: Invalid user admin from 161.97.112.53 port 54656\nAug 31 13:59:53 r3 sshd[3734]: Invalid user user from 2.56.59.30 port 45564\n<\/pre>\n\n\n\n<p>Or we can count it (after two hours). We had 644 ssh login attempts to our server:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cat \/var\/log\/secure | grep Invalid | wc -l\n644<\/pre>\n\n\n\n<p>So, find I will install fail2ban services, for ban these IPs&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">dnf install -y fail2ban-firewalld.noarch<\/pre>\n\n\n\n<p>Now, we must create a new jail.local, where we define actions for those IPs and services. So, create this file and add some variables. If you wish, adjust by your needs:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/fail2ban\/jail.local\n\n[DEFAULT]\n# Ban IP\/hosts for 24 hour ( 24h*3600s = 86400s):\nbantime = 86400\n \n# An ip address\/host is banned if it has generated \"maxretry\" during the last \"findtime\" seconds.\nfindtime = 900\nmaxretry = 2\n\n# Enable sshd protection\n[sshd]\nenabled = true\n<\/pre>\n\n\n\n<p>Now, we can start\/restart fail2ban services and view its status. And next, use fail2ban client to view detailed status:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl restart fail2ban\nsystemctl status fail2ban\n\nfail2ban-client status\nfail2ban-client status sshd<\/pre>\n\n\n\n<p>Now, we must see some IPs, that are already banned by our fail2ban. If you wish to manually ban\/unban IP, lets do this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">fail2ban-client unban 192.168.1.1\nfail2ban-client set sshd banip 18.188.124.148\n<\/pre>\n\n\n\n<p>Or you can set your trusted IPs to whitelist:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/fail2ban\/jail.conf\n\n[DEFAULT]\nignoreip = 127.0.0.1\/8 192.168.1.1<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Time server &#8211; chronyd<\/h2>\n\n\n\n<p>Now, we install chronyd service, for obtain and distributing  time from world to our subnets. So, install chronyd, and set localisation to you system<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">dnf install chrony -y\nsystemctl enable chronyd\ntimedatectl set-timezone Europe\/Bratislava\ntimedatectl<\/pre>\n\n\n\n<p>Now, edit some variables in configurations file for chronyd. Add some servers from pool, and edit local subnets, where we delived time:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/chrony.conf\n\npool 2.centos.pool.ntp.org iburst\npool 1.centos.pool.ntp.org iburst\npool 3.centos.pool.ntp.org iburst\nallow 192.168.1.0\/24<\/pre>\n\n\n\n<p>Now start\/restart our service, and check, if it is working:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl restart chronyd\nsystemctl status chronyd.service\nchronyc sources<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">IPV4 forwarding<\/h2>\n\n\n\n<p>As the first things, we must check, if our system has enabled IP forwarding in kernel. Check it out:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sysctl -a | grep ip_forward\n\nnet.ipv4.ip_forward = 1<\/pre>\n\n\n\n<p>If not, enable it:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sysctl -w net.ipv4.ip_forward=1\n\nvim \/etc\/sysctl.d\/99-sysctl.conf\n#insert:\nnet.ipv4.ip_forward=1<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up nftables <\/h2>\n\n\n\n<p>In out environment, we use nftables. It is default backend firewall module in Centos 8\/ RHEL 8.  It is already managed by firewalld, but we gonna use native nft command. The nftables is able to collapse firewall management for IPv4, IPv6 and bridging into the single command line utility: nft.<\/p>\n\n\n\n<p>So, at the beginning (or before run our later nft script), we disable firewalld utility:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl disable --now firewalld\nsystemctl mask firewalld\nreboot<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Creating Tables and Chains<\/h3>\n\n\n\n<p>Rebooting the system after disabling firewalld will ensure that we have no remnants of the tables, chains and rules added by firewalld. We start up with nothing in-place. Unlike iptables, nftables does not have any tables or chains created by default. Managing nftables natively requires us to create these objects:<\/p>\n\n\n\n<p><strong>protocol family<\/strong>: At the top level of the configuration tree we have protocol families: ip, ip6, arp, bridge, netdev and inet. Using inet we can cater for both IPv4 and IPv6 rules in the one table.<\/p>\n\n\n\n<p><strong>table<\/strong>: Below the protocol family we define tables to group chains together. The default table was the filter table in iptables but we also had other tables such as the nat table.<\/p>\n\n\n\n<p><strong>chain<\/strong>: A chain presents a set of rules that are read from the top down. We stop reading once we match a rule. When creating a chain in nftables we can specify the type of chain \u2013 we use the filter type, the hook \u2013 we will be working with input hook and a priority. The lower the number the higher the priority and the highest priority chain takes precedence. We will also specify the default policy which defines the action if no rule is met.<\/p>\n\n\n\n<p>To list existing tables, we shouldn\u2019t have any, we use the following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nft list tables<\/pre>\n\n\n\n<p>Now, we create s script file, in which will be all our rules. So, you have to do some learning about nft. Here you are the basic rules:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cat \/root\/nftables.sh<br><br>#!\/bin\/bash<br># the executable for nftables<br>nft=\"\/usr\/sbin\/nft\"<br><br># wan and lan ports. Home routers typically have two ports minimum.<br>wan=ens2<br>lan=ens1<br>wan6=ens3<br><br># flush\/reset rules<br>${nft} flush ruleset<br><br>#create tables called \"filter\" for ipv4 and ipv6<br>${nft} add table ip filter<br>${nft} add table ip6 filter<br><br># one more table called 'nat' for our NAT\/masquerading<br>${nft} add table nat<br><br>#create chains<br>${nft} add chain ip filter input { type filter hook input priority 0 ; }<br>${nft} add chain ip filter output {type filter hook output priority 0 ; }<br>${nft} add chain ip filter forward {type filter hook forward priority 0 ; }<br>${nft} add chain ip filter postrouting {type filter hook postrouting priority 0 ; }<br>${nft} add chain nat postrouting {type nat hook postrouting priority 100 ; }<br><br># and for ipv6<br>${nft} add chain ip6 filter input { type filter hook input priority 0 ; }<br>${nft} add chain ip6 filter output {type filter hook output priority 0 ; }<br>${nft} add chain ip6 filter forward {type filter hook forward priority 0 ; }<br>${nft} add chain ip6 filter postrouting {type filter hook postrouting priority 0 ; }<br>${nft} add chain ip6 filter nat {type nat hook postrouting priority 100 ; }<br><br>#FORWARDING RULESET<br><br>#forward traffic from WAN to LAN if related to established context<br>${nft} add rule filter forward iif $wan oif $lan ct state { established, related } accept<br><br>#forward from LAN to WAN always<br>${nft} add rule filter forward iif $lan oif $wan accept<br><br>#drop everything else from WAN to LAN<br>${nft} add rule filter forward iif $wan oif $lan counter drop<br><br>#ipv6 just in case we have this in future.<br>${nft} add rule ip6 filter forward iif $wan6 oif $lan ct state { established,related } accept<br>${nft} add rule ip6 filter forward iif $wan6 oif $lan icmpv6 type echo-request accept<br><br>#forward ipv6 from LAN to WAN.<br>${nft} add rule ip6 filter forward iif $lan oif $wan6 counter accept<br><br>#drop any other ipv6 from WAN to LAN<br>${nft} add rule filter forward iif $wan6 oif $lan counter drop<br><br>#INPUT CHAIN RULESET<br>#============================================================================<br>${nft} add rule filter input ct state { established, related } accept<br><br># always accept loopback<br>${nft} add rule filter input iif lo accept<br># comment next rule to disallow ssh in<br>${nft} add rule filter input tcp dport ssh counter log accept<br><br>#accept DNS, SSH, from LAN<br>${nft} add rule filter input iif $lan tcp dport { 53, 22 } counter log accept<br>#accept DNS on LAN<br>${nft} add rule filter input iif $lan udp dport { 53 } accept<br><br>#accept ICMP on the LAN,WAN<br>${nft} add rule filter input iif $lan ip protocol icmp accept<br>${nft} add rule filter input iif $wan ip protocol icmp accept<br><br>${nft} add rule filter input counter drop<br><br>################# ipv6 ###################<br>${nft} add rule ip6 filter input ct state { established, related } accept<br>${nft} add rule ip6 filter input iif lo accept<br>#uncomment next rule to allow ssh in over ipv6<br>#${nft} add rule ip6 filter input tcp dport ssh counter log accept<br><br>${nft} add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept<br><br>${nft} add rule ip6 filter input counter drop<br><br><br>#OUTPUT CHAIN RULESET<br>#=======================================================<br># allow output from us for new, or existing connections.<br>${nft} add rule filter output ct state { established, related, new } accept<br><br># Always allow loopback traffic<br>${nft} add rule filter output iif lo accept<br><br>${nft} add rule ip6 filter output ct state { established, related, new } accept<br>${nft} add rule ip6 filter output oif lo accept<br><br><br>#SET MASQUERADING DIRECTIVE<br>${nft} add rule nat postrouting masquerade<\/pre>\n\n\n\n<p>So, this script can be run by:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sh \/root\/nftables.sh<\/pre>\n\n\n\n<p>And now, we can view our filter and rules:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nft list tables\nnft list table filter<\/pre>\n\n\n\n<p>This is only for this session, and after reboot, there will be empty list. To ensure, that filter persist reboot, run following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nft list ruleset > \/etc\/sysconfig\/nftables.conf<br>systemctl enable nftables.service<br>reboot<br>nft list table ip filter<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Install and create own DNS resolver<\/h2>\n\n\n\n<p>Now we set up a local DNS resolver on CentOS 8\/RHEL 8, with the widely-used BIND9 DNS software.<\/p>\n\n\n\n<p>Be aware that a DNS server can also called a name server. Examples of DNS resolver are 8.8.8.8 (Google public DNS server) and 1.1.1.1 (Cloudflare public DNS server). <\/p>\n\n\n\n<p>Normally, your computer or router uses your ISP\u2019s DNS resolver to query domain names in order to get an IP address. Running your own local DNS resolver can speed up DNS lookups, because<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The local DNS resolver only listens to your DNS requests and does not answer other people\u2019s DNS requests, so you have a much higher chance of getting DNS responese directly from the cache on the resolver.<\/li>\n\n\n\n<li>The network latency between your computer and DNS resolver is eliminated (almost zero), so DNS queries can be sent to root DNS servers more quickly.<\/li>\n<\/ol>\n\n\n\n<p>If you own a website and want your own DNS server to handle name resolution for your domain name instead of using your domain registrar\u2019s DNS server, then you will need to set up an authoritative DNS server, which is different than a DNS resolver. BIND can act as an authoritative DNS server and a DNS resolver at the same time<\/p>\n\n\n\n<p>BIND (Berkeley Internet Name Domain) is an open-source DNS server software widely used on Unix\/Linux due to it\u2019s stability and high quality.<\/p>\n\n\n\n<p>So, install it first, check version and start it. The BIND daemon is called <strong>named<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>dnf update\ndnf install bind bind-utils<\/strong>\n\n<strong>named -v<\/strong>\n    BIND 9.11.26-RedHat-9.11.26-6.el8 (Extended Support Version) &lt;id:3ff8620&gt;\n\n<strong>systemctl start named\nsystemctl enable named<\/strong><\/pre>\n\n\n\n<p>Usually, DNS queries are sent to the UDP port 53. The TCP port 53 is for responses size larger than 512 bytes. You must adjust your firewall to allow tcp and udp packets on port 53.<\/p>\n\n\n\n<p>We can check the status of the BIND name server.:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">rndc status<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Configurations for a Local DNS Resolver<\/h3>\n\n\n\n<p>Out of the box, the BIND9 server on CentOS\/RHEL provides recursive service for localhost only. Outside queries will be denied. Edit the BIND main configuration file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/named.conf<\/pre>\n\n\n\n<p>In the <code>options<\/code> clause, you can find the following two lines:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">listen-on port 53 { 127.0.0.1; };\nlisten-on-v6 port 53 { ::1; };<\/pre>\n\n\n\n<p>This makes <code>named<\/code> listen on localhost only. If you want to allow clients in the same network to query domain names, then comment out these two lines. (add double slashes at the beginning of each line)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ listen-on port 53 { 127.0.0.1; };\n\/\/ listen-on-v6 port 53 { ::1; };<\/pre>\n\n\n\n<p>Find and adjust these variables:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">allow-query { localhost; 192.168.1.0\/24; };\nrecursion yes;\n \/\/ hide version number from clients for security reasons.\n version \"not currently available\";\n \/\/ enable the query log\n querylog yes;<\/pre>\n\n\n\n<p>Now, check our config (silent output if is OK), and restart named:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">named-checkconf\nsystemctl restart named<\/pre>\n\n\n\n<p>Now, you have enabled DNS resolver. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create own DNS zone, dnssec signed<\/h3>\n\n\n\n<p>If you want your own DNS server for your domain, accessible from world and you don&#8217;t want you domain provider, to be a DNS server for this domain, let read next.<\/p>\n\n\n\n<p>First, create a new database file for this domain:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/var\/named\/db.example.com\n\n;\n; BIND data file for example.com\n;\n$TTL 604800\n@       IN      SOA     example.com.     root.example.com.        (\n        2021090608      ; Serial\n        3600            ; Refresh\n        86400           ; Retry\n        2419200         ; Expire\n        3600    )       ; Default TTL\n\n        IN      NS      ns1.example.com.\n\n@\tIN\tA\t212.5.215.172\nns1     IN      A       212.5.215.172\nwww\tIN\tCNAME\tns1\n<\/pre>\n\n\n\n<p>We have three dns names, that direct to our domain (www, ns1 and the domain itself: example.com). Now, we must edit the main configuration file for named, and add point to this zone\/domain\/file. And add som variables for dnssec. Now we comment out previously commented two lines and edit some variables:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/named.conf\n\n        listen-on port 53 { any; };\n        listen-on-v6 port 53 { any; };\n        allow-query { any; };\n        dnssec-enable yes;\n        dnssec-validation yes;\n        recursion no;\n\n\nzone    \"example.com\" IN {\n        type master;\n        file \"db.example.com\";\n        allow-transfer { none; };\n};\n<\/pre>\n\n\n\n<p>Now, check the config and restart named:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">named-checkconf\nnamed-checkzone example.com \/var\/named\/db.example.com\nsystemctl restart named<\/pre>\n\n\n\n<p>Now, we can reach our domain from world, if domain registrator set NameServer (ns1.example.com) to point to our public IP and let us for managing our dns zone.<\/p>\n\n\n\n<p>Now, we can continue for dnssec with some theory:<\/p>\n\n\n\n<p>DNS by itself is not secure. DNS was designed in the 1980s when the Internet was much smaller, and security was not a primary consideration in its design. As a result, when a recursive resolver sends a query to an authoritative name server, the resolver has no way to verify the authenticity of the response. The resolver can only check that a response appears to come from the same IP address where the resolver sent the original query. But relying on the source IP address of a response is not a strong authentication mechanism, since the source IP address of a DNS response packet can be easily forged, or <em>spoofed<\/em>.<\/p>\n\n\n\n<p>DNSSEC strengthens authentication in DNS using digital signatures based on public key cryptography. With DNSSEC, it&#8217;s not DNS queries and responses themselves that are cryptographically signed, but rather DNS data itself is signed by the owner of the data&#8230;. More about this: <a href=\"https:\/\/www.icann.org\/resources\/pages\/dnssec-what-is-it-why-important-2019-03-05-en\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.icann.org\/resources\/pages\/dnssec-what-is-it-why-important-2019-03-05-en<\/a><\/p>\n\n\n\n<p>So, lets create a key-pairs:<\/p>\n\n\n\n<p>1 &#8211; Create a Zone Signing Key (ZSK)<br>2 &#8211; Create a Key Signing Key (KSK)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>cd \/var\/named\ndnssec-keygen -a RSASHA256 -b 2048 -r \/dev\/urandom example.com\ndnssec-keygen -a RSASHA256 -b 4096 -r \/dev\/urandom -f KSK example.com<\/strong>\n\neg: Generating key pair......................++ .............................................................................................................................................................................................................++\nKexample.com.+007+18522<\/pre>\n\n\n\n<p>The directory will now have 4 keys &#8211; private\/public pairs of ZSK and KSK. We have to add the public keys which contain the <strong>DNSKEY<\/strong> record to the zone file. For example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cat Kexample.com.+008+18522.key &gt;&gt; \/var\/named\/db.example.com\ncat Kexample.com.+008+56121.key &gt;&gt; \/var\/named\/db.example.com<\/pre>\n\n\n\n<p>Now, edit owner permisions of these keys to named:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">chown named Kexample.com*<\/pre>\n\n\n\n<p>And now, check our zone and if is everything ok, sign the zone:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>named-checkzone example.com \/var\/named\/db.example.com<\/strong>\n\nzone example.com\/IN: loaded serial 2021090901\nOK\n\n<strong>dnssec-signzone -A -3 $(head -c 1000 \/dev\/urandom | sha1sum | cut -b 1-16) -N INCREMENT -o example.com -t db.example.com<\/strong>\n\nVerifying the zone using the following algorithms: RSASHA256.\nZone fully signed:\nAlgorithm: RSASHA256: KSKs: 1 active, 0 stand-by, 0 revoked\n                      ZSKs: 1 active, 0 stand-by, 0 revoked\ndb.example.com.signed\nSignatures generated:                       13\nSignatures retained:                         0\nSignatures dropped:                          0\nSignatures successfully verified:            0\nSignatures unsuccessfully verified:          0\nSigning time in seconds:                 0.020\nSignatures per second:                 649.707\nRuntime in seconds:                      0.025<\/pre>\n\n\n\n<p>Above command created a signed zone file for example.com zone: db.example.com.signed.<\/p>\n\n\n\n<p>We are now required to edit zone configuration to use new file instead of db.example.com old file, and add som variables:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim \/etc\/named.conf\n\nzone    \"example.com\" IN {\n        type master;\n        file \"<strong>db.example.com.signed<\/strong>\";\n        allow-transfer { none; };\n   # DNSSEC keys Location\n   <strong>key-directory \"\/var\/named\/\";<\/strong> \n\n   # Publish and Activate DNSSEC keys\n   <strong>auto-dnssec maintain;\n\n<\/strong>\n   # Use Inline Signing\n<strong>   inline-signing yes;\n<\/strong>\n};<\/pre>\n\n\n\n<p>Now, check named config, and our zone:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>named-checkconf\nnamed-checkzone example.com \/var\/named\/db.example.com.signed<\/strong>\n\nzone example.com\/IN: loaded serial 2021090902 (DNSSEC signed)\nOK\n\n<strong>systemctl restart named<\/strong><\/pre>\n\n\n\n<p>And now, we can try our zone, if dnssec is working:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>dig DNSKEY example.com. +multiline<\/strong>\n\n; &lt;&lt;&gt;&gt; DiG 9.11.26-RedHat-9.11.26-6.el8 &lt;&lt;&gt;&gt; DNSKEY example.com. +multiline\n;; global options: +cmd\n;; Got answer:\n;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 19926\n;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1\n\n;; OPT PSEUDOSECTION:\n; EDNS: version: 0, flags:; udp: 4096\n;; QUESTION SECTION:\n;example.com.\t\tIN DNSKEY\n\n;; ANSWER SECTION:\nexample.com.\t\t604795 IN DNSKEY 256 3 8 (\n\t\t\t\tAwEAAbfz4OM2hWwBKTlQuvP+q5SxJWkQo0SYbHLjJKiw\n\t\t\t\tJ0qwgsTsXQM8uYa8tHcFdZFSNu7Qrs14CHEGimsufpGO\n\t\t\t\td1TgRUeJxDI9Yrl27hg+rd+58HUiwkxQpTOFS4FXx2mw\n\t\t\t\t\/TsTREFtiC16H2ZA\/Bgw4N\/C4HO2JfBIyOt6YdA4labS\n\t\t\t\tKBGtBXcR5tbckXh706JwAaVFliDDnFNkPh0L5UUDpkUG\n\t\t\t\teKLVis4n7WqQdtv0\/WRbURm0HiyMwAdovvr1q1YUmRni\n\t\t\t\txAN\/5lBAWOID6YETSx+QROEoxkveHJpctE3knRTC3ZnR\n\t\t\t\tKqF6z25nrWv9oJeghk6niq6Eyt5+dibMLJaJ8Cc=\n\t\t\t\t) ; ZSK; alg = RSASHA256 ; key id = 56241\nexample.com.\t\t604795 IN DNSKEY 257 3 8 (\n\t\t\t\tAwEAAduWjrX7Rv6A3b7VA0t0Q2dQLawRP9F4A86eIScD\n\t\t\t\tFpDpGFjp8T6U2nFcNrqlQrgXKJ5DUXIxkWZd2mbtjTWn\n\t\t\t\tTDp6cjnuudYispnV3EyiXhhpGUyEBlOGUvZ8f55xd3EK\n\t\t\t\tf+p1inceqzYL0VV2qaAMmPBR8gUhtDDj9hlIhJfEC0b9\n\t\t\t\tJeIVHO01U0IIFsHCDNnykLwpibeK1e\/TWwQ3ipoaHshJ\n\t\t\t\tdJS3ZdfFS0zHBn736v5wneJVusR5AaBcFbeVWdW3bZR9\n\t\t\t\tEPwh97nVEdvZk2UVfQtDy3KNpwzbvaB19EbBdaeiDEr8\n\t\t\t\t8+Tho3vRuo1uphhFtTbWWMHnyY5WKDcmBEtAVH1WhsEW\n\t\t\t\tp4cyMa4ASVz8Zr10b88g7EN8i4lm6X7hNFVVjZ75N+MI\n\t\t\t\tYNbuxHF1C7FDh3ACKVMk8qveYQx37iS8G5RID8COzpej\n\t\t\t\tN9L+o\/3xlAd6k8hnKqvU+TE1xcOM2Q936Rpudzs6vKDz\n\t\t\t\tQvy5h94J9b\/5ZPkb4CPOto9jWzT\/t\/lv96cvtG8qKTDH\n\t\t\t\tSpg9WtTf42DSdFHflTof5Fqlzjy2Fq0UQXlJNGjOHoii\n\t\t\t\tTBcQATlSC1yxQALj3+1fvTSe9yZ+PGwxnGUKijTvfcpP\n\t\t\t\tOetqN8T9261Kv5u\/kOKjDM9DxLYYdfkqV6dKAooWaIUS\n\t\t\t\twPFkk+zbN7YnNoasHRGSF+\/hC+lV\n\t\t\t\t) ; KSK; alg = RSASHA256 ; key id = 18544\n<\/pre>\n\n\n\n<p>We have configured <strong>DNSSEC<\/strong> on our master DNS server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">DHCP server on lan<\/h2>\n\n\n\n<p>Now, we install dhcp server on our centos server. I have interface for this server: ens22, and our gateway will be 192.168.15.9 and clients will have IPs from range: 192.168.15.20-192.168.15.100. We must have a static IP from this subnet on this interface.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">dnf makecache\ndnf install dhcp-server<\/pre>\n\n\n\n<p>Now, create own configuration file for dhcp server, or copy example and adjust:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cp \/usr\/share\/doc\/dhcp-server\/dhcpd.conf.example \/etc\/dhcp\/dhcpd.conf\n#or:\nvim \/etc\/dhcp\/dhcpd.conf<\/pre>\n\n\n\n<p>And edit this variables as you fit:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">option domain-name \"example.com\";\noption domain-name-servers ns1.example.com;\n\ndefault-lease-time 600;\nmax-lease-time 7200;\n\nddns-update-style none;\nauthoritative;\nlog-facility local7;\n\nsubnet 192.168.15.0 netmask 255.255.255.0 {\n}\nsubnet 192.168.15.0 netmask 255.255.255.0 {\n  range 192.168.15.20 192.168.15.100;\n  option routers 192.168.15.9;\n  option domain-name-servers 192.168.15.9;\n}\n<\/pre>\n\n\n\n<p>Now, we can start dhcp server and view our logs. I have 8 interfaces, but only on this is dhcp enabled:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl start dhcpd.service\nsystemctl enable dhcpd.service\ntail \/var\/log\/messages -f\n\n<em>No subnet declaration for ens18 (no IPv4 addresses).\n ** Ignoring requests on ens18.  If this is not what\nyou want, please write a subnet declaration\nin your dhcpd.conf file for the network segment\nto which interface ens18 is attached. **<\/em><\/pre>\n\n\n\n<p>Now, enable UDP port 67 to access dhcp server. Look below for this port. So edit your nftables.sh script and apply it and view:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">netstat -tulpen | grep dhcp\nudp        0      0 0.0.0.0:67\n\n<em>iif \"ens22\" udp dport { 67 } accept<\/em><\/pre>\n\n\n\n<p>And start some PC on this network and we will see at logs:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">tail -n 10 \/var\/log\/messages\ndhcpd[]: DHCPREQUEST for 192.168.15.20 from ac:5a:32:98:0c:xx (pc1) via ens22\ndhcpd[]: DHCPACK on 192.168.15.20 to ac:5a:32:98:0c:xx (pc1) via ens22\ndhcpd[]: DHCPREQUEST for 192.168.15.20 from ac:5a:32:98:0c:xx (pc1) via ens22\ndhcpd[]: DHCPACK on 192.168.15.20 to ac:5a:32:98:0c:xx (pc1) via ens22\n<\/pre>\n ","protected":false},"excerpt":{"rendered":"<p>Today, I need to rebuild and create a new one linux router. It will work with many networks, there will be DHCP and DNS server as well. So, at first, we will secure our server on service: ssh. I assume, that you already have enabled firewalld and public zone, only for sshd service. And internal &hellip; <a href=\"https:\/\/www.gonscak.sk\/?p=767\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">How to create a router from Centos 8 Stream<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[136,116,134,135,137,138,132],"class_list":["post-767","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-bind","tag-centos-8","tag-dns","tag-fail2ban","tag-named","tag-nftables","tag-sshd"],"_links":{"self":[{"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/posts\/767","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=767"}],"version-history":[{"count":30,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/posts\/767\/revisions"}],"predecessor-version":[{"id":1039,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=\/wp\/v2\/posts\/767\/revisions\/1039"}],"wp:attachment":[{"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=767"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=767"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gonscak.sk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=767"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}