• No results found

Existing Implementations of Translators

Translators have been implemented for some products. The description of these implementations groups them by service. Although the actual translation depends mostly on the service and the target implementation, all translators have a similar entry point. A template for the document root “/” selects the service this translator is for. The template for that service first creates the wrapping <service> element (of the configuration namespace, this time) and copies the target for that node type from the nodetype’s service declaration. As mentioned previously, the type resolution copies the targets there for just this purpose. The example in Listing 22 prepares an Ethernet interfaces translator.

Listing 22: Typical initialisation of a translator. <xsl:template match="/"> <xsl:apply-templates select="vn:node/vn:hardware" /> </xsl:template> <xsl:template match="vn:hardware"> <service name="ethernet"> <xsl:copy-of select="../tr:nodetype/tr:service[@name=’ethernet’]/tr:target" /> <xsl:apply-templates select="vn:ethernet"/> </service> </xsl:template>

Red Hat Linux was the primary target operating system for the translation experiments. Red Hat supports all of the services implemented in Verinec. Note that Linux distributions derived from Red Hat are often also supported by the Red Hat translators, namely the free Red Hat variant Fedora. The same holds for Debian Linux translators, which can be used for Ubuntu and other Debian based distributions.

8.5.1

Generic Service

The generic-service element designates no real service. But there is no “magic” built into the translation framework. Generic service is treated like a normal service. This means the translation framework expects to find meta information to locate the correct translator and restrictor. As there is nothing to do, the none translator mentioned in Section 8.4.1 is used.

If generic services are used, which is typically the case after importing an existing network (see Section 8.8), each node type should declare the none implementation for generic-service. The restrictor will produce a warning that a generic service cannot be translated. Ideally, the Verinec user would replace all generic services with their actual services and provide configuration. If generic services are present on translation, it is good to warn before the distribution happens.

8.5. EXISTING IMPLEMENTATIONS OF TRANSLATORS 93

8.5.2

Hardware Interfaces

Interface configuration is highly distribution specific. But the number of features is manageable and translation straightforward. Verinec supports Red Hat, Debian, Windows XP and Cisco. Red Hat Linux

Red Hat Linux uses file based configuration for its interfaces. As Red Hat expects one separate file for each interface, the translator generates several result-file elements, one for each ethernet- binding encountered. The files are located in /etc/sysconfig/networking-scripts/ and named ifcfg-<interface-name>. In Chapter 7, the format of the files has been discussed in depth. For distribution, the cp and scp methods are suitable.

To notify the system of the new configuration, /etc/init.d/network restart has to be called in the post-process. As stopping the interfaces can interrupt the ssh connection, nohup is used. Nohup executes the program and does not stop if the user logs out before it is completed. Restarting the network interfaces produces some output on the command line, resulting in a warning written to the Verinec log file. As long as each line ends with “[Done]”, the warning is irrelevant.

Debian Linux

Debian uses one single file for all interfaces. It is called /etc/network/interfaces and contains statements to configure all interfaces. Listing 23 shows a typical translator output for Debian. Post-processing is almost the same as for Red Hat, except that the init script is named networking instead of network. The command is thus nohup /etc/init.d/networking restart.

Listing 23: Network configuration for Debian. <configuration>

<service name="ethernet"> <post-process>

<command execute="nohup /etc/init.d/networking restart"/> </post-process>

<result-file filename="/etc/network/interfaces"> #Network configuration linux-debian created by Verinec auto lo

iface lo inet loopback auto eth0

iface eth0 inet static address 172.16.1.1 netmask 255.255.0.0 gateway 172.16.1.254 hwaddr 00:0C:29:74:DC:60 #peerdns not supported. </result-file>

</service> </configuration>

Windows XP

Windows interface configuration is based on the registry. In Verinec, WMI is used for ma- nipulating the network interfaces. Windows network configuration has been implemented by [Zurkinden, 2005]. The WMI distributor interprets XML specifications to script operations. List- ing 24 shows the script to set the first network interface to a static network address. The wmi element specifies the WQL statement to retrieve the scripting object. Network interfaces are mod- ified using the scripting object Win32 NetworkAdapterConfiguration. Methods on this object allow to set DHCP or static addresses, DNS servers and the gateway. Each method element indi- cates a method to be called with the parameters specified by param. The reason param-value is a

94 CHAPTER 8. VERINEC IMPLEMENTATION

child element rather than an attribute of param is that the parameters expect arrays. There could be more than one param-value for the methods.

Listing 24: WMI script for network interfaces. <configuration>

<service name="ethernet"> <result-wmi>

<!-- Ethernet card configured by VeriNeC: Ethernet card eth0 --> <wmi class="Win32_NetworkAdapterConfiguration"

namespace="root/cimv2" wqlKey="Index" wqlKeyValue="1"> <method name="EnableStatic">

<param name="IPAddress" type="ArrayOfString"> <param-value value="172.16.1.1" />

</param>

<param name="SubnetMask" type="ArrayOfString"> <param-value value="255.255.0.0" />

</param> </method>

<method name="SetGateways">

<param name="DefaultIPGateway" type="ArrayOfString"> <param-value value="172.16.1.254" /> </param> </method> </wmi> </result-wmi> </service> </configuration> Cisco

Interfaces in Cisco routers have a special meaning. The first interface (Ethernet0) is the LAN side, while the WAN side is Ethernet1. Routers with several LAN ports incorporate them as an unmanaged switch on OSI layer 2 in front of Ethernet0. IP assignment and other network settings are only possible on OSI layer 3. Some devices use Ethernet2 in a three-legged firewall setup.10 If

the device supports port mirroring, that port can also have a higher name. Listing 25 shows the configuration commands for the LAN interface.

Listing 25: Cisco interface configuration. ip default-gateway 172.16.1.254

Interface Ethernet0

ip address 172.16.1.1 255.255.0.0 ip access-group 101 in

ip access-group 102 out

The translator written by [Ehret, 2005] generates configuration in Cisco IOS format and should be used together with the Cisco distribution method. For Cisco, the mapping of packet filter chains to interfaces is done at the interface declaration. Because there can be only one declaration block per interface, the ethernet translator has to generate the mapping of interfaces to chains. As Cisco uses numbers for the chains, the interface position is used to generate the chain number. Interface 0 has 101 for input filtering, 102 for output filtering, and so on. The actual filters are translated by the packet-filter translator.

10A three-legged firewall allows to get part of the security achieved with a DMZ: it contains a third port for the

8.5. EXISTING IMPLEMENTATIONS OF TRANSLATORS 95

8.5.3

Packet Filter

The packet filter is one of the more complex services configured by Verinec. Support has been implemented for the Netfilter framework omnipresent on Linux distribution and for Cisco routers. Netfilter

The iptables application can be installed on all Linux systems. But as has been mentioned in Section 7.2.3, configuration formats vary. To solve this problem and avoid writing similar but slightly different translators because of that, Verinec does not directly generate the configuration file. It generates a result-file containing an executable script that configures iptables as desired. Before the new configuration can be set, existing configuration has to be removed. The pre- process commands are iptables -F and iptables -X. The first deletes the rules in all chains, the second deletes all unreferenced chains. Afterwards, the target system’s filter table is completely empty. Linux distribution specific methods are used to produce the final configuration. For Red Hat, there is an iptables script in the init.d directory. The result-file is copied to the target machine at /tmp/iptables-init and executed by the first post-process. Then the Red Hat init.d script of iptables is told to store the current configuration of iptables permanently by calling /etc/init.d/iptables save. The last post-process is rm /tmp/iptables-init to clean up. Debian has no iptables script in init.d. Iptables configuration has to be put into the folder /etc/network/if-up.d/, which is even simpler to do than the method for Red Hat. The target of the result file is the if-up.d directory and no post-process commands are required.

The translator has to take care of a couple of specific problems. If the target of a gosub-action (the -J parameter) is not yet defined, the script aborts with an error. Thus, all chains are created without content before the rules for each of them are defined. Because Netfilter does not support per interface chain, the translator has to add tests for interfaces in the interface-filter-mappings as described in Section 8.3.2.

To avoid unecessary jumps, the chain names INPUT, OUTPUT and FORWARD are treated as special cases. The straightforward translation would be to generate all chains and add jumps to the default chains to the chains referenced in global-in, global-out and forward attributes of the packet-filters. This would generate one unnecessary jump. Instead, the referenced chains are directly created as the respective default chains. Trying to create a chain with one of the build-in names produces an error anyway. If however, one of the default chains is also referenced from elsewhere, this could however lead to problems.

Cisco

Cisco’s philosophy of assigning filter chains is rather different from Netfilter. There are no global chains, but each interface can be assigned one chain for incoming packets, one for outgoing. As has been mentioned, there are usually only two interfaces, one for the LAN, one for the WAN. Contrary to a Linux host, filtering packets addressed at or originating from localhost is not important on a router. The packets have to pass the ‘in’ chain of the interface they arrive on and the ‘out’ chain for the interface they are to be resent from.

The keyword to define packet filter chains in IOS is access-list. Until the most recent versions, the Cisco IOS could only use numbers and not names for access lists. In addition, the range of a number for an access list identifies its type. Lists with numbers between 1 and 99 are IP standard lists, from 100 to 199 IP access lists with extended functionality, 700 to 799 for MAC access lists and so on. Within Verinec, extended IP lists are used with a range from 100 to 199. As there are at most two access lists per interface, there is no risk of running out of available numbers.

The XSL translator was initially written by [Ehret, 2005], but had to be rewritten by the author of this thesis to operate correctly. Translation does not begin with the chains, but with the interfaces. For each interface, the interface-filter-mappings are checked to see whether an interface specific chain is defined. Of the global chains, only the forward chain is used, if it is defined. It is appended after both the in and the out chain for each interface. As the semantics of global-in and global-out chains are controlling traffic to the local host, they are completely ignored.

Chains referenced by the mapping or globally are duplicated for each reference. The reason is that Cisco access lists cannot check for the current interface. If the rule is only used by one interface, the test can be done at translation: if the chain is not for the interface in question, the

96 CHAPTER 8. VERINEC IMPLEMENTATION

rule is left out - it would always evaluate to false. If the chain is for this interface, the rule is used without any interface test, as that test would always evaluate to true.11 A more serious problem is that Cisco IOS does not support jumps from one access-list to another. The gosub-action can thus not be translated. Under one condition, translation can still be done. If the packet-match-list is empty, this is an unconditional jump and the chain can simply be copied in place. If there is a match-list, it is theoretically possible to copy the referenced chain in place, prepending each rule with the jump criteria. In practice, this is very difficult, as the Cisco syntax defines the order of the tests in a rule. And if there are cycles in the jumps, the translator would loop endlessly between the chains. The risk of endless loops in the translator is already introduced when expanding chains referenced without criteria, but at least such a cycle is probably a mistake, as it could provoke an endless loop when being executed by the filter implementation.

Rules for a Cisco device look like in Listing 25. As has been mentioned above in Section 8.5.2 on ethernet translation, attributing the chains to the interfaces has to be done in the ethernet translator. The translator here relies on the ethernet translation to produce the access-group statements. The configuration script is executed in the context of the existing configuration. To redefine the access-list, it has to be emptied first as explained in Section 6.2.3. Otherwise, the new tests would just be appended to the existing list. The translator only removes access-lists it is going to redefine. It is possible for the running-config to contain other access-lists, but as they are not referenced by the interfaces, they are not used and thus do no harm.

In this example, the Verinec configuration contains no interface specific chain for port 0, but a global forward chain. The forward chain contained only one rule, an unconditional jump to the RH-Firewall chain. The firewall chain is copied right into this chain. The rule after the comment ! match-state not supported is an example for the risks of unsupported features. The rule access-list 101 permit any any originates from a test in the Verinec XML to accept all packets in states ‘established’ and ‘related’. As this cannot be translated here, we end up with a rule accepting all packets, rendering the rest of the list unused. This is rather dangerous, as the default policy of the firewall chain would have been to reject (deny) all other packets. The last rule can never be reached, but this is not due to a bug. It is the default policy of the forward chain, which is overwritten by the policy of the firewall chain.

Listing 25: Snippet of a Cisco packet filter configuration. ... ! Ethernet port 0 Interface Ethernet0 ip address 63.236.73.147 255.255.255.0 ip access-group 101 in no access-list 101

! Appending global chain FORWARD to in for interface eth0 ! chain FORWARD

! chain RH-Firewall-1-INPUT

access-list 101 permit icmp any any 255 access-list 101 permit udp any any eq 5353 access-list 101 permit udp any any eq 631 access-list 101 permit tcp any any eq 631 ! match-state not supported

access-list 101 permit any any ! match-state not supported

access-list 101 permit tcp any any eq 22 access-list 101 deny any any

access-list 101 permit any any

11Duplication of one chain used by different interfaces would not be necessary if it contains no interface tests at

8.5. EXISTING IMPLEMENTATIONS OF TRANSLATORS 97

8.5.4

Routing

Routing configuration on non-router devices is usually not necessary. According to [Dooley, 2002], it is even bad design to have clients or servers participating in routing protocols. Usually, the gate- way information found in static interface definition or provided by a DHCP response respectively is enough information for network connectivity. PC operating systems set their routes automatically based on the interfaces IP’s and networks. Problems with the setup usually indicate a problem in the network rather than the requirement to change the PC routing information.

Translation has been implemented for Cisco routers by [Ehret, 2005]. The Verinec configuration does not define dynamic routing configuration, so only static routing is supported by the translator. For simplicity, route-filters have also been left out, although it would be possible to implement some of them using Cisco routing policies. The translator produces ip route commands, as shown in Listing 26. Each route matches on an IP and mask. The third IP number is the next hop, of which Cisco supports only one in static routing. At the end of route lines, a metric can specify the costs for that route. For dropping packets (blackhole routing), a special interface with the name Null0 exists. It is used in the middle line of the example listing.

Listing 26: Snippet of a Cisco router configuration. <configuration> <service name="routing"> <result-file filename="cisco-routing"> ip route 10.10.10.0 255.255.255.0 63.29.19.19 10 ip route 192.168.0.0 255.255.0.0 Null0 ip route 0.0.0.0 0.0.0.0 129.32.23.10 12 </result-file> </service> </configuration>

Routing configuration has not been implemented for any PC operating system. On linux, static routing is done by calling the route program with the parameters for each route. This is usually done in a startup script. The location for the file is distribution specific, but the file contains calls to route. The route-filters have to be translated into iptables commands on linux. As the XML Schema fragment is inspired by the iptables, this would again be straightforward and very similar to packet filtering.

8.5.5

DNS Server

DNS configuration has been discussed in Section 8.3.3 Verinec contains translators for BIND and djbdns.

BIND

The configuration format of BIND (Berkeley Internet Name Domain) has been discussed in Sec- tion 7.2.4. The Verinec translator produces all necessary files for the configuration: the global /etc/named.conf as well as the files for each zone and reverse zones.

djbdns

The djbdns translator has been implemented by [Awesso, 2005]. djbdns [Bernstein, 2007] follows a somewhat different philosophy. Bernstein’s software adheres strictly to the principle of “one tool one task”. djbdns is actually a collection of tools. The for important programs are

dnscache: Treat client requests (forward queries to other DNS servers and cache responses for repeated queries).

tinydns: Provide a DNS server for a domain configured locally. axfrdns: Handle zone transfer requests from other hosts.

98 CHAPTER 8. VERINEC IMPLEMENTATION

Additional tools are used to compile the text-based configuration files into speed optimised database files. dnscache and axfrdns need no special configuration once they are installed. For tinydns, the translator generates the configuration file (usually simply called data) and invokes