📜 ⬆️ ⬇️

Software Internet gateway for a small company (Shorewall, OpenVPN, OSPF). Part 1

I present while two articles focused on the "continuing" system administrators, for experienced I hardly open something new.
In these articles, we will look at building an Internet gateway on linux, allowing you to link several company offices, and provide limited access to the network, traffic prioritization (QoS) and simple load balancing with redundancy between two providers.
Specifically in this part:

And in the second part will be considered:

In the third part :

In the fourth part :


Everything described below is valid for CentOS 7.1 (and above, the 6th series is also suitable, but with some minor features)

We presume that we have:

In general, my ip plan meant reservation / 21 networks for each branch from the range of 172.16.0.0/12. Each band / 21 is cut into subnets for different needs (more details in the next article).

The simplest setting is Shorewall


')
For those who have not heard before, Shorewall is an add-on to the iptables utility for configuring NetFilter in the Linux kernel. By itself, iptables is not too complicated, but when the gateway configuration becomes large and difficult because of this, it is not easy to understand this amount of iptables commands.
Various self-made scripts or, for a long time not self-made, systems similar to Shorewall come to the rescue in such situations.

In Shorewall, everything revolves around the concept of "zone". Hosts are included in the zone (by specifying interfaces or directly networks and / or individual addresses).
Let's look in the zones file
# # Shorewall -- /etc/shorewall/zones # # For information about this file, type "man shorewall-zones" # # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-zones.html # ############################################################################### #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall red ipv4 grn ipv4 tun ipv4 


Here I identified three zones (for the ipv4 protocol), in addition to the special “fw” zone, which embodies the gateway itself.

The time has come to put interfaces into these zones (we will not use individual hosts yet), but before that we will make some changes to the file:
params
 # # Shorewall -- /etc/shorewall/params # # Assign any variables that you need here. # # It is suggested that variable names begin with an upper case letter # to distinguish them from variables used internally within the # Shorewall programs # # Example: # # NET_IF=eth0 # NET_BCAST=130.252.100.255 # NET_OPTIONS=routefilter,norfc1918 # # Example (/etc/shorewall/interfaces record): # # net $NET_IF $NET_BCAST $NET_OPTIONS # # The result will be the same as if the record had been written # # net eth0 130.252.100.255 routefilter,norfc1918 # ############################################################################### IF_RED1=eth0 IF_GRN=eth1 NET_GRN=172.16.0.0/23 IF_TUN=tap+ #LAST LINE -- DO NOT REMOVE 


In this file, you can set different variables, which we will later use in other files, and which help to make the config more portable between systems. Now we have our physical interfaces and local branch subnet here. Note that tap + talks about using a mask, under which any tapX falls (except for just “tap”).
And now the file:
interfaces
 # # Shorewall -- /etc/shorewall/interfaces # # For information about entries in this file, type "man shorewall-interfaces" # # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-interfaces.html # ############################################################################### ?FORMAT 2 ############################################################################### #ZONE INTERFACE OPTIONS red $IF_RED1 dhcp,routeback,optional grn $IF_GRN dhcp,routeback,optional tun $IF_TUN dhcp,routeback,optional 


Here, too, nothing particularly difficult, the options tell us that:

Let's make a few changes to the file “shorewall.conf”, it is quite large, I will give its truncated view (only changed values):
shorewall.conf
 ############################################################################### # # Shorewall Version 5 -- /etc/shorewall/shorewall.conf # # For information about the settings in this file, type "man shorewall.conf" # # Manpage also online at http://www.shorewall.net/manpages/shorewall.conf.html ############################################################################### # STARTUPENABLED ############################################################################### STARTUP_ENABLED=Yes ############################################################################### # FIREWALL OPTIONS ############################################################################### BLACKLIST="ALL" CLAMPMSS=Yes IP_FORWARDING=Yes ################################################################################ # PACKETMARKLAYOUT ################################################################################ TC_BITS=14 PROVIDER_BITS=8 PROVIDER_OFFSET=16 MASK_BITS=16 ZONE_BITS=0 


All parameters are quite understandable, but the “PACKET MARK LAYOUT” section will be discussed in the following sections, “BLACKLIST” specifies the type of blocked packets (all) for banned addresses, also for the future.
It's time to create default policies:
policy
 # # Shorewall -- /etc/shorewall/policy # # For information about entries in this file, type "man shorewall-policy" # # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-policy.html # ############################################################################### #SOURCE DEST POLICY LOG LIMIT: CONNLIMIT: # LEVEL BURST MASK $FW all ACCEPT grn all ACCEPT red all DROP tun grn ACCEPT tun red REJECT tun $FW ACCEPT 


Keywords mean the following:

In the third column, you can register several more parameters, one of which is info, will set the logging of this policy (it makes sense for DROP and REJECT, and then ACCEPT will fill you up with logs).

The given policy is primitive and not suitable for serious projects, it corresponds to the setting of most home routers, but for the very start it will suit us.
It remains a little bit, namely to set up masquerading (which in the IPv6 era will not be necessary):
masq
 # # Shorewall -- /etc/shorewall/masq # # For information about entries in this file, type "man shorewall-masq" # # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-masq.html # ################################################################################################################################### #INTERFACE:DEST SOURCE ADDRESS PROTO PORT(S) IPSEC MARK USER/ SWITCH ORIGINAL PROBABILITY # GROUP DEST $IF_RED1 $NET_GRN 


Obviously, everything that goes towards the interface $ IF_RED1 from the $ NET_GRN network needs to be masked. The third column ADDRESS is used for SNAT.

For tracking and a corresponding change in the firewall rules, in response to enabling / disabling the interface, a small script will help us:
/etc/NetworkManager/dispatcher.d/30-shorewall.sh
 #!/bin/bash IF=$1 #   ,     STATUS=$2 #     case $STATUS in up) #      shorewall enable $IF shorewall6 enable $IF ;; down) #      shorewall disable $IF shorewall6 disable $IF ;; esac 


Having given the command “systemctl enable shorewall.service && systemctl restart shorewall.service”, we will use our firewall settings, and nothing will work (well, almost), we do not have enough smallness: there is no caching DNS AND DHCP servers (let's not we customize all client machines).

The simplest setting is dnsmasq



This service does its job very well, and the network / 23 is not a problem for it, and the simplicity and flexibility of the settings makes it very suitable for our situation.
Since the configuration file is large, I will bring it in a reduced form too:
/etc/dnsmasq.conf
 # Configuration file for dnsmasq. # # Format is one option per line, legal options are the same # as the long options legal on the command line. See # "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. # If you want dnsmasq to listen for DHCP and DNS requests only on # specified interfaces (and the loopback) give the name of the # interface (eg eth0) here. # Repeat the line for more than one interface. interface=eth1 # Set the domain for dnsmasq. this is optional, but if it is set, it # does the following things. # 1) Allows DHCP hosts to have fully qualified domain names, as long # as the domain part matches this setting. # 2) Sets the "domain" DHCP option thereby potentially setting the # domain of all systems configured by DHCP # 3) Provides the domain part for "expand-hosts" domain=domain.local # This is an example of a DHCP range where the netmask is given. This # is needed for networks we reach the dnsmasq DHCP server via a relay # agent. If you don't know what a DHCP relay agent is, you probably # don't need to worry about this. dhcp-range=172.16.0.50,172.16.0.150,255.255.254.0,12h # Set the DHCP server to authoritative mode. In this mode it will barge in # and take over the lease for any client which broadcasts on the network, # whether it has a record of the lease or not. This avoids long timeouts # when a machine wakes up on a new network. DO NOT enable this if there's # the slightest chance that you might end up accidentally configuring a DHCP # server for your campus/company accidentally. The ISC server uses # the same option, and this URL provides more information: # http://www.isc.org/files/auth.html dhcp-authoritative 



I think it’s not necessary to explain anything here, set the interface on which to service DNS and DHCP requests, set the range of addresses to be distributed, set some parameters passed to DHCP, and set the authoritarian mode of operation.
Now, after “systemctl enable dnsmasq.service && systemctl restart dnsmasq.service”, we will have access to the Internet from internal clients (as soon as they receive a DHCP lease).

OpenVPN setup



I think this part will not be difficult for anyone at all, but we will give these steps:
  1. Install packages from epel: openvpn easy-rsa
  2. Copy the / usr / share / easy-rsa folder into / etc / openvpn and rename it to easy-rsa
  3. Go to / etc / openvpn / easy-rsa and, if necessary, edit the vars file
  4. Run: ". ./Vars && ./clean-all && ./build-dh && openvpn --genkey --secret ./keys/ta.key &&. / Build-ca && ./build-key-server server # Hi from Gentushnik (how to install Gentoo in one team, and this is possible)!

We also need a server configuration file:
/etc/openvpn/inter-lan.conf
 port 1194 proto udp topology subnet dev tap0 ca ./easy-rsa/keys/ca.crt cert ./easy-rsa/keys/server.crt key ./easy-rsa/keys/server.key dh ./easy-rsa/keys/dh1024.pem client-config-dir ./ccd/inter-lan/ client-to-client keepalive 10 120 tls-server tls-auth ./easy-rsa/keys/ta.key 0 cipher AES-256-OFB comp-lzo no auth SHA256 status /var/run/openvpn/inter-lan.status sndbuf 393216 rcvbuf 393216 push "sndbuf 393216" push "rcvbuf 393216" mode server push "topology subnet" ifconfig 172.16.3.1 255.255.255.128 ifconfig-pool 172.16.3.2 172.16.3.126 255.255.255.128 ifconfig-pool-persist /var/run/openvpn/inter-lan.db 3600 verb 1 


The default parameters file passed to OpenVPN for the client:
/ etc / openvpn / ccd / inter-lan / DEFAULT
 push "comp-lzo no" 


Client configuration template file:
/etc/openvpn/easy-rsa/templates/inter-lan.conf
 client port 1194 dev tap4 proto udp remote <   > 1194 tls-client ns-cert-type server cipher AES-256-OFB auth SHA256 verb 1 comp-lzo no <ca> -----CERTIFICATE-CA----- </ca> <cert> -----CERTIFICATE----- </cert> <key> -----KEY----- </key> key-direction 1 <tls-auth> -----TLS----- </tls-auth> 


And auxiliary samopinsky script:
/etc/openvpn/easy-rsa/build-ovpn.sh
 #!/bin/bash # $2 -        [ "$2" == "-r" ] && ./build-key $1 CWD=$(pwd) RUN=$(dirname $0) cd "$RUN" mkdir -p ../ovpn/$1 for i in $(ls -1 ./templates/); do TEMPLATE=$(basename $i .conf) sed -e '/-----CERTIFICATE-CA-----/{r /etc/openvpn/easy-rsa/keys/ca.crt' -e 'd}' ./templates/${TEMPLATE}.conf | \ sed -e '/-----CERTIFICATE-----/{r /etc/openvpn/easy-rsa/keys/'"$1.crt"'' -e 'd}' | \ sed -e '/-----KEY-----/{r /etc/openvpn/easy-rsa/keys/'"$1.key"'' -e 'd}' | \ sed -e '/-----TLS-----/{r /etc/openvpn/easy-rsa/keys/ta.key' -e 'd}' > ../ovpn/$1/${TEMPLATE}-$1.ovpn done cd "$CWD" 


I use the tap interface, because tun is routed by the OpenVPN core, and this is configured using the iroute directive. And the sadness is, if behind one server there is another one to which we need a route, we need to explicitly register this route in ccd, the same iroute directive, which, apart from the usual routes, will create unnecessary difficulties (what difficulties I say, write in the OSPF section).

Now we will generate a configuration for the client:
./build-ovpn.sh <client name> -r
Create a ccd file for the client:
/ etc / openvpn / ccd / inter-lan / <client name>
 #    ,       :),   ,   DEFAULT 


Then you need to copy the file from the / etc / openvpn / ovpn / <client name> / <client name> .ovpn directory to the client computer (gateway) and place it in / etc / openvpn / with the extension ".conf"
Run openvpn on the client and server:
 systemctl enable openvpn@< conf    conf>.service && systemctl start openvpn@< conf    conf>.service 

And the result is only on the server! The client is in trouble. Shorewall is to blame for everything, or rather our policy, we did not allow connections from the Internet (red zone)!
Let's add the allowing rule to the file:
/ etc / shorewall / rules
 # # Shorewall -- /etc/shorewall/rules # # For information on the settings in this file, type "man shorewall-rules" # # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-rules.html # ###################################################################################################################################################################################################### #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS SWITCH HELPER # PORT(S) PORT(S) DEST LIMIT GROUP ?SECTION ALL ?SECTION ESTABLISHED ?SECTION RELATED ?SECTION INVALID ?SECTION UNTRACKED ?SECTION NEW #    : /usr/share/shorewall/macro.OpenVPN #  ,     /etc/shorewall,      OpenVPN(ACCEPT) red $FW # ,      : #ACCEPT red $FW udp 1194 


We execute "shorewall restart" and see that the client has successfully connected.
Let's try to ping client ip issued by OpenVPN, all Ok. Now the network behind the client (172.16.8.0/23), and again a bummer, ip in the tunnel is pinged, but the network is not, since there are no routes, OSPF will provide them to us.

Configure OSPF Dynamic Routing Protocol in quagga



Here on Habré there is a series of large articles devoted to dynamic routing, how it works, etc., right there I will give some practical squeeze out of them and the setting itself.

I came to the use of OSPF after the company in which I work, acquired almost a dozen branch offices and representative offices, and the tunnels between them were built not only with a star, but were also direct between individual branches (so that the most actively interacting went in a straight line, and not in the central node). When I got a little swollen by the number of routes and their settings, built a bicycle (a script that rebuilt static configs of routes using a prescribed map), the bicycle was beautiful, hexagonal wheels, ten pedals, and you ride it for a ride, while walking next to it ... in the swamp, I thought, and quickly found out about OSPF and began the implementation.

We will need the quagga package, after installation, copy the initial configuration file and start the service:
 cp /usr/share/doc/quagga-0.99.22.4/ospfd.conf.sample /etc/quagga/ospfd.conf && chown quagga. /etc/quagga/ospfd.conf systemctl enable ospfd.service && systemctl start ospfd.service 

Now we need to configure the ip address on the loopback interface, which among other things (you will find the meaning in other articles) will play the role of router-id.
Add the following lines to the / etc / sysconfig / network-scripts / ifcfg-lo file:
 IPADDR2=172.16.248.1 NETMASK2=255.255.255.255 

And re-raise the interface: ifup lo
Now let's connect to the ospfd service and configure it:
 telnet localhost ospfd #   zebra ospfd# enable #    ospfd# configure terminal #    ospfd(config)# password <> #     ospfd(config)# hostname < > #  ,     ospfd(config)# log syslog #      ospfd(config)# interface <   tap0> #  ospfd(config-if)# ip ospf network point-to-multipoint #  tap    (    ,        ) ospfd(config-if)# exit #    ospfd(config)# router ospf #   ospf ospfd(config-router)# router-id 172.16.248.1 #   ospfd(config-router)# passive-interface default # OSPF    ospfd(config-router)# no passive-interface < > #    ,        ospf (     tap0) ospfd(config-router)# network 172.16.0.0/12 area 0.0.0.0 # ,     ,   ,     .    /12    ,        ospfd(config-router)# write memory #     

Summary configuration file:
/etc/quagga/ospfd.conf
 ! ! Zebra configuration saved from vty ! 2016/01/05 14:20:08 ! hostname ospfd password zebra log stdout log syslog ! ! ! interface eth0 ! interface eth1 ! interface lo ! interface tap0 ip ospf network point-to-multipoint ip ospf cost 3 ! router ospf ospf router-id 172.16.248.1 passive-interface default no passive-interface tap0 network 172.16.0.0/12 area 0.0.0.0 ! line vty ! 

You may notice that the file reflects the configuration commands that we entered into the console. Is it possible that you can see “ip ospf cost 3”, with which I have indicated the cost of the interface (again for the future, when there will be different routes to one point).

By copying this file to another gateway (which is associated with this by OpenVPN) and making the appropriate edits, we will get a working configuration between the two gateways (the ospfd service on the second gateway also needs to be started).
Now the “ip route list” command should show us something like this:
 default via 192.168.10.1 dev eth0 proto static metric 100 172.16.0.0/23 dev eth1 proto kernel scope link src 172.16.0.1 metric 100 172.16.3.0/25 dev tap0 proto kernel scope link src 172.16.3.1 172.16.3.1 dev tap0 proto zebra 172.16.8.0/23 via 172.16.3.2 dev tap0 proto zebra metric 13 172.16.11.1 via 172.16.3.2 dev tap0 proto zebra metric 3 172.16.12.129 via 172.16.3.2 dev tap0 proto zebra metric 3 172.16.248.2 via 172.16.3.2 dev tap0 proto zebra metric 13 192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.37 metric 100 192.168.10.1 dev eth0 scope link src 192.168.10.37 

Routes with “proto zebra” are just added using OSPF.

I recommend to everyone, use dynamic routing, even if you have only two branches. When they become more, you will not be difficult to add another node to the network.
And of course, the proposed OSPF configuration is rather primitive, wait for the more complicated options with examples in the next article (or read the articles of more competent comrades, in fact, I have not studied OSPF deeply enough).

Source: https://habr.com/ru/post/274639/


All Articles