Section 35.1. Objective 1: Basic Networking Configuration


35.1. Objective 1: Basic Networking Configuration

Notice how this Objective doesn't sound much more advanced than the Level 1 networking Objectives. Don't be deceived. While the tasks may seem simple when put into black and white, the LPI Level 2 Exam tends to assume that you've run into problems in your previous work and have learned to troubleshoot networking issues. So, instead of simply thinking to yourself "Yes, I know the route command or the ifconfig command," think to yourself, "How are these commands commonly used in a production environment?" Think of the commands in context.

35.1.1. Network Configuration Utilities, and What Lies Beneath

Quite a few configuration tools exist for configuring a network card on a Linux system to be a part of an IP network. Those tools vary widely between the Linux distributions and sometimes between the different versions of the same distribution as well, but they generally do the same thing. For instance, a tool called netconfig exists in both Red Hat/Fedora and Slackware but is not the exact same utility. Fedora also has a curses-based tool called system-config-network-tui that lets you configure the network connection on network interface cards, ISDN adapters, and modems. The Novell/SuSE systems wanted administrators to use YAST/Yast2 (YAST is text based, Yast2 is GUI based) to configure networking. Ubuntu Linux (www.ubuntu.org) currently contains a configuration tool called the Network Administration Tool as part of the Gnome Desktop Environment.

This author never uses graphical or screen-based, distribution-specific tools for configurationnot to look like the biggest alpha-geek in the room but because the tools often don't get the configuration right. All the fancy networking applets and applications do is create or alter system network configuration files, which are in simple text formats and have traditionally been created by hand. I find I usually end up having to open my trusty text editor and fix the configuration files the old-fashioned way anyway, so I may as well start out with the pure files.

Because the LPI Exam was put together by experts in the field, they, too, have found that the best way to configure a system is to go in and start editing text files. So let's get down to it and discuss the text files that your networking subsystem uses.

35.1.2. Common Network Configuration Files

Because network interface cards (NICs), with the exception of modems and ISDN adapters, are usually activated at boot time, Linux distributions include configurations for the cards in system files. Depending upon the system you use, you will find one of the following:

  • A file called /etc/network/interfaces

  • A series of files in the /etc/sysconfig/network-scripts directory

35.1.2.1. The /etc/network/interfaces file

This is found in Debian-based distributions, including such popular variants as Ubuntu and Knoppix. It contains ifconfig parameters, such as broadcast and netmask addresses, and can optionally specify commands to be run before or after a network card is brought up or down.

A sample /etc/network/interfaces file is:

 auto lo iface lo inet loopback auto eth0 iface eth0 inet static         address 192.168.0.20         netmask 255.255.254.0         broadcast 192.168.1.255         gateway 192.168.0.1 

The file must contain at least two entries for a network-aware system: one for the loopback interface (lo) and one for another interface (in this case, eth0). To comment out an entry, simply put a # character at the start of the line.

The syntax is relatively simple. The iface entry simply defines an interface (eth0). The entry contains the word static, which means the interface is configured manually, not using DHCP. If you wished this interface to use DHCP, you would change the line to read as follows:

 iface eth0 inet dhcp 

The four lines below the iface line correspond to typical ifconfig options. If you change the interface to use DHCP, this invalidates the ifconfig options, but you do not need to comment the lines out. Once your system reads dhcp in the configuration file, it ignores any other information in the file for that particular interface.

The line before the iface entry, auto eth0, means this particular interface will be activated automatically at boot time.

My particular system is a laptop that (luckily enough) supports both my standard Ethernet card (eth0), and my Atheros wireless A-G card (ath0). Don't get flustered in the LPI Exam if an interface isn't called eth0 or eth1. You will find that the underlying principles covered will remain the same, even if some names are different. Following is an example of the information I use to configure my wireless card:

 auto ath0 iface ath0 inet static         address 192.168.40.40         netmask 255.255.255.0         network 192.168.40.0         broadcast 192.168.40.255         gateway 192.168.40.1         # wireless-* options are implemented by the wireless-tools package         wireless-mode managed         wireless-essid JAMESSTANGER         wireless-key1 ee453fq449g0fg354wghgj12b4         # dns-* options are implemented by the resolvconf package, if installed         dns-nameservers 192.168.40.4         wireless-key ee453fq449g0fg354wghgj12b4 

This example shows that Debian systems can contain the access point's Secure Set Identifier (SSID), as well as all necessary Wireless Equivalent Privacy (WEP) information. (WEP is an outmoded protocol and is no longer considered to be secure, but some wireless cards have not yet adopted the better WPA security.) Also, many Linux systems do not yet support WPA.

35.1.2.2. The /etc/sysconfig/network-scripts directory

Red Hat and Fedora systems store their interface configuration files in a directory named /etc/sysconfig/network-scripts/, where each network interface has a separate file. For example, the directory in the old Red Hat system that I use as a router contains at least the files listed in Table 35-1.

Table 35-1. Sample network configuration files in /etc/sysconfig/network-scripts

Filename

Purpose

ifcfg-lo

Configures the loopback interface

ifcfg-eth0

Configures the first Ethernet interface

Ifcfg-eth1

Configures the second Ethernet interface

Ifcfg-eth2

In case the router had even a third Ethernet interface

ifup

Used to activate any interface you specify

ifdown

Dectivates any interface you specify

ifup-ppp

Used to activate Point-to-Point Protocol (PPP) dial-up connections

ifdown-ppp

Used to deactivate PPP connections

ifup-ipv6

Activates IPv6 on an interface

ifdown-ipv6

Deactivates an IPv6 interface

ifup-isdn

Activates an ISDN connection

ifdown-isdn

Deactivates an ISDN connection


An example of a simple /etc/sysconfig/network-scripts/ifcfg-eth0 file follows:

 DEVICE=eth0 ONBOOT=yes BOOTPROTO=static IPADDR=172.22.1.45 NETMASK=255.255.255.0 GATEWAY=172.22.1.1 

The syntax for this file is quite simple; standard configuration options are specified as KEYWORD=value pairs. One detail worth noting is the BOOTPROTO enTRy. static means that the eth0 interface uses a manually entered IP address. To use DHCP, change the value to dhcp. If, for some reason, you wish your system to use the old bootp protocol, you can also specify bootp. The ONBOOT enTRy simply specifies whether you wish the device to be activated at boot time. If you do not wish to activate the device, set the value to no.

However, tools and runlevel scripts are all wrappers around the two main network interface configuration tools ifconfig and route. A Linux system administrator must know by heart how to use those commands. ifconfig takes several parameters; the IP address itself is essential.

35.1.3. Using ifconfig

When the IP address is configured from DHCP, you won't usually need to use ifconfig directly. But it's important to know how to check interfaces and bring them up if the system hasn't done so automatically.

The ifconfig command may be used on any kind of network interface, not only physical Ethernet or Token Ring network cards. PPP (dial-up) interfaces, loopback interfaces, and VPN tunnel endpoints may all be configured with ifconfig. Even though ifconfig defaults to the IP (Version 4) address type, it is also used when configuring other address families such as IPX, IPv6, and AppleTalk. Here is the basic syntax of the command:

 ifconfig [interface] [option] [address] 

The interface is a device name, such as the familiar lo or eth0. The network card represented by the device must have been detected by the kernel before it can be configured by ifconfig. The address is the IP address to and from which traffic will go through the interface.

Following are the most frequently used options. Note that the -a option contains a hyphen (because it applies to the command in general) whereas the other options (which apply to the interface) do not.


-a

Lists all interfaces, including down and unconfigured ones.


up

Enables the interface.


down

Disables the interface. After being disabled, the interface keeps any configured addresses, so if you enable the interface later, it still is associated with the addresses.


hw class address

Reports address as the hardware address of the specified class (described in the text).


netmask

netmask

Sets the netmask on the given interface.

35.1.3.1. Virtual interfaces

ifconfig can configure virtual interfaces "on top of" the regular interface. For instance, based on the eth0 interface, you could activate the virtual interfaces eth0:0 and eth0:1. This kind of configuration is often found on web servers hosting lots of web sites and domains (when SSL certificates are in use, the IP address involved must belong to one and only one hostname) or on shell servers offering hostnames to be used on IRC and similar services.

To use virtual interfaces on a 2.2.x kernel (or earlier), support for interface aliasing must be explicitly enabled.

Following is an example of how to configure one interface to use multiple IP addresses:

 ifconfig eth0:1 192.168.40.41 netmask 255.255.255.0 

The resulting output of ifconfig is:

 eth0      Link encap:Ethernet  HWaddr 00:0B:5D:71:FE:D1           inet addr:192.168.40.40  Bcast:255.255.255.0  Mask:255.255.255.0           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           RX packets:140371 errors:0 dropped:0 overruns:0 frame:0           TX packets:105052 errors:0 dropped:0 overruns:0 carrier:0           collisions:7218 txqueuelen:1000           RX bytes:93678761 (89.3 MiB)  TX bytes:14520288 (13.8 MiB)           Interrupt:19 eth0:1    Link encap:Ethernet  HWaddr 00:0B:5D:71:FE:D1           inet addr:192.168.40.41  Bcast:192.168.40.255  Mask:255.255.255.0           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           Interrupt:19 

35.1.3.2. Other common uses for ifconfig

You can also use the ifconfig command to:

  • Activate or deactivate an interface. This can also be done through the ifup and ifdown commands.

  • Set the subnet mask: useful when a system has been placed onto a different subnet, but retains the same IP address.

  • Set the broadcast address. If you have to change the subnet mask, you may have to change the broadcast address, as well.

  • Create a custom MAC address (also known as the Ethernet address).

The last task in the list is useful in some situations in which the ISP allows only a particular MAC address to participate on the network. For example, many broadband users have had to register an NIC with their ISP, but have then had to swap out their NIC or change the entire system. The ifconfig command allows systems with a 2.4 kernel or newer to "spoof" a MAC address. To do this, the device driver for the NIC must also support this feature.

To create a custom MAC address, you need to specify the hardware class. The most common class is ether, which stands for Ethernet. Additional classes include ax25, ARCnet, and neTRom, but for the LPI test, you need to know only about the ether class.

An example follows of how to use ifconfig to configure a system with the custom MAC address 1:02:03:04:05:06:

 ifconfig eth0 192.168.40.40 netmask 255.255.255.0 broadcast 192.168.40.255 \          hw ether 1:02:03:04:05:06 

35.1.3.3. Examples

Here are some examples of how ifconfig is used in a production environment.

The following command sets the IP address of the eth0 NIC to 192.168.45.12. Because no netmask is specified, the command uses the default (class C) broadcast address and network mask that apply to addresses in the 192.x.x.x range.

 ifconfig eth0 192.168.45.12 

The following command explicitly specifies the IP address, network mask, and broadcast address:

 ifconfig eth0 172.20.16.34 netmask 255.255.255.128 broadcast 172.20.16.127 

The following deactivates the interface. Obviously, this is not a command you should use when doing administration remotely on your system.

 ifconfig eth0 down 

The following activates a virtual network interface card based on the eth0 interface, which must have been configured previously. The virtual address does not inherit any netmask or broadcast properties from the main interface; defaults are used. ifconfig will not protest if you configure virtual interfaces with different network properties from the main interface, but you may experience erratic or inconsistent behavior.

 ifconfig eth0:0 192.168.45.13 

The following sequence of commands sets an IP address on a network interface card, then disables and enables the network card. After each command affecting the interface, another command displays the state of the interface. Note that the IP address is still there when the interface is down and that the interface is explicitly shown as UP when it is enabled.

 # ifconfig eth0 10.20.30.4 # ifconfig eth0 eth0      Link encap:Ethernet  HWaddr 00:60:97:16:4A:EF           inet addr:10.20.30.4  Bcast:10.255.255.255  Mask:255.0.0.0           UP BROADCAST MULTICAST  MTU:1500  Metric:1           ... # ifconfig eth0 down # ifconfig eth0 eth0      Link encap:Ethernet  HWaddr 00:60:97:16:4A:EF           inet addr:10.20.30.4  Bcast:10.255.255.255  Mask:255.0.0.0           BROADCAST MULTICAST  MTU:1500  Metric:1           ... # ifconfig eth0 up # ifconfig eth0 eth0      Link encap:Ethernet  HWaddr 00:60:97:16:4A:EF           inet addr:10.20.30.4  Bcast:10.255.255.255  Mask:255.0.0.0           UP BROADCAST MULTICAST  MTU:1500  Metric:1           ... 

35.1.4. The route Command

The route command is capable of setting up complicated routing arrangements, but most sites use it simply to set up the default gateway. You can use the command to set or delete static routes, as well as to view the kernel routing table. Complicated routing arrangements nowadays are done through routing protocols rather than manual configuration, although there are advanced manual techniques you don't need to know for the LPI test.

Each host uses its default gateway to access resources outside the locally defined network, such as the rest of the Internet. The host at the IP address you set to be the default gateway is usually a router or routing firewall. This gateway must have an IP address within your network. Quite often, the gateway is located at the first usable IP address in a network.

35.1.4.1. Syntax and frequently used options

The syntax for the route command is:

 route [ add | delete ] [ -net | -host ] [address] \       [netmask netmask] [gw address] [interface] 

Each command can add a route to either an external network (-net) or a particular host (-host). A gw gateway address can be specified without either a -net or a -host argument, in which case the command specifies a default gateway to use for traffic from this host.

35.1.5. Common Uses

If your Linux system receives its IP address from a DHCP server, your system automatically sets the default route and other network parameters. You won't usually need to manually configure the default gateway using route. However, the LPI Exam expects you to be able to manually connect a Linux system to a network.

The following example sets the default gateway, assuming that 192.168.40.1 is the address of the hub on your local area network that accepts traffic from your host:

 route add default gw 192.168.40.1 

The keyword default is a built-in alias for the IP address 0.0.0.0, which means "any host." This command uses the defaults for the network and netmask (0.0.0.0), and is therefore equivalent to:

 route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.40.1 

The default netmask of 0.0.0.0, similar to the 0.0.0.0 IP address, may be translated as "any host in any IP network." Any other routes you specify are consulted first; if the address of your destination can't be reached through those explicit routes, the system uses the default gateway.

During the exam, you'll likely be given a readout from the route command. Make sure that you can read it and interpret it. Here is an example:

 james@james:~ $ route -n Kernel IP routing table Destination     Gateway         Genmask         Flags Metric Ref    Use Iface localnet              *         255.255.255.0   U     0      0        0 ath0 localnet              *         255.255.255.0   U     0      0        0 eth0 default    192.168.40.1         0.0.0.0         UG    0      0        0 eth0 james@james:~ $ 

The keyword localnet means that ath0 and eth0 are local interfaces. The keyword default refers to the default gateway. The other basic elements you should understand are the flags; U means the route is up (usable) while G means the address represents a gateway.

In this example, the default gateway used by both eth0 and ath0 is 192.168.4.1. The zeros in the first column of the final entry indicate the default gateway for these interfaces. Note that the destination IP address (0.0.0.0), the netmask (0.0.0.0), and the gateway address (192.168.40.1) are what was configured in the earlier route command.

The previous command included the -n option, which has the route command specify numerical addresses instead of hostnames. Using this option guarantees that you receive all interface-specific information, even if a name resolution problem occurs.

If you enter the command without the -n option, you see output such as:

 james@james:~ $ route Kernel IP routing table Destination     Gateway         Genmask         Flags Metric Ref    Use Iface localnet              *         255.255.255.0   U     0      0        0 ath0 localnet              *         255.255.255.0   U     0      0        0 eth0 default    192.168.40.1         0.0.0.0         UG    0      0        0 eth0 james@james:~ $ 

The -C option causes route to display the complete routing cache stored on the local system; this shows how traffic has been sent to and received from other systems recently.

To add an explicit host routing entry for the host 172.25.50.33, which will be reached through a different gateway from the default one, enter:

 route add -host 172.25.50.33 gw 192.168.45.2 

To add a network to the routing table, routing traffic to it through the gateway found at address 192.168.45.3, enter:

 route add -net 10.0.0.0 netmask 255.0.0.0 gw 192.168.45.3 

To delete the default route, use either of the following commands:

 route del default gw 192.168.45.1 route del -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.45.1 

Finally, when it comes to using the route command in a production environment, remember the following:


If a DNS problem occurs, the output of the route command might hang.

There might be other reasons for the output to hang, but name resolution is the most common. This is why, on many commands shown in this chapter for troubleshooting, it is sometimes useful to use the -n option. The attempt to contact a DNS server for name resolution might cause the output to hang if the network is not functioning properly.


The netstat -r and netstat -nr commands give output similar to route and route -n commands, respectively.

However, the route command allows you to add and delete routing table information, whereas the netstat command allows you to only review settings.

35.1.6. ARP and Related Commands

The Internet Protocol (IP) is a Layer 3 protocol, and the NIC in the Linux system is a Layer 2 device. On a local network, the nodes know each other only by the unique 6-byte MAC (Media Access Control) address programmed into each NIC.

Because of this, devices that use IP require a protocol to map between the two layers. That protocol is the Address Resolution Protocol (ARP). ARP creates a mapping between a given IP address and the MAC address of the NIC where the IP address is configured. ARP does not map the other wayi.e., from MAC address to IP address. That is the task of the Reverse Address Resolution Protocol (RARP).

When two IP-enabled nodes need to communicate, the kernel on the originating node hands the IP packet to the NIC and says, "This is a packet for the IP address aaa.bbb.ccc.ddd; please find the recipient." The NIC then broadcasts a request to find out which network interface card (if any) has the aaa.bbb.ccc.ddd address configured on its Layer 3. This request is called an ARP request.

Perhaps the best way to understand ARP is to view it in action. Below is a tcpdump session that shows an ARP request and the resulting reply. This capture is of a ping packet that was sent from a system with the IP address of 192.168.0.20 to a system with an IP address of 192.168.1.18; ping uses an ICMP request and reply.

 06:10:03.003044 arp who-has 192.168.1.18 tell 192.168.0.20 06:10:03.003092 arp reply 192.168.1.18 is-at 00:c0:f0:30:1d:5e 06:10:03.796840 IP 192.168.0.20 > 192.168.1.18: icmp 64: echo request seq 1 06:10:03.796992 IP 192.168.1.18 > 192.168.0.20: icmp 64: echo reply seq 1 

In other words, the ARP request and reply had to execute successfully before the ping ICMP messages could be sent.

ARP entries are cached on the hosts in the network for a period of time, which is defined by the /proc/sys/net/ipv4/neigh/eth0/gc_stale_time file (assuming that the system's network interface is eth0). By default, ARP entries are considered stale after 60 seconds.

The arp command shows the ARP cache. A typical display, run from the 192.168.0.20 system, might be:

 # arp Address                  HWtype  HWaddress           Flags  Mask            Iface 192.168.0.1              ether   08:00:20:77:2B:CB   C      eth0 192.168.1.101            ether   00:30:1B:B0:9F:A1   C      eth0 192.168.1.203            ether   00:08:74:04:0A:D8   C      eth0 192.168.1.18             ether   00:C0:F0:30:1D:5E   C      eth0 

35.1.6.1. arp command syntax

Following is the synax and description for the arp command:

 arp [options] [hostname] 

Frequently used options include:


-d hostname

Remove hostname from ARP cache.


-f file

Statically map hostnames to MAC addresses based on entries in a file. The file format is exactly like the parameters to the -s option: a hostname and MAC address separated by whitespace, followed by any other applicable parameters.


-n

Do not resolve hostnames.


-s

hostname MAC_address

Statically map hostname to MAC_address. This option is often used for proxy ARP configurations, in which one system may respond to ARP requests on behalf of another. When used for proxy ARP, the parameter pub must be added:

 arp -s hostname MAC_adress pub 

If you are temporarily adding an ARP entry that should be flushed after the regular ARP timeout (60 seconds), add the parameter temp to the entry.

35.1.6.2. Example #1

This example performs some basic ARP manipulation.

Add a temporary ARP entry to a host's ARP cache:

 # arp -s 192.168.0.45 00:02:03:F6:7C:4B temp # arp -n Address                  HWtype  HWaddress           Flags Mask            Iface 192.168.0.45             ether   00:02:03:F6:7C:4B   C                     eth1 192.168.0.20             ether   00:01:02:F7:7C:4B   C                     eth1 

Add a static ARP entry to a host's ARP cache:

 # arp -s 192.168.0.45 00:02:03:F6:7C:4B # arp -n Address                  HWtype  HWaddress           Flags Mask       Iface 192.168.0.45             ether   00:02:03:F6:7C:4B   CM               eth1 192.168.0.20             ether   00:01:02:F7:7C:4B   C                eth1 

Remove a static ARP entry from a host's cache:

 # arp -d 192.168.0.45 # arp -n Address                  HWtype  HWaddress           Flags Mask        Iface 192.168.0.20             ether   00:01:02:F7:7C:4B   C                 eth1 

35.1.6.3. Example #2

This shows how ARP works behind the scenes.

Here, a connection to a nonexistent host is attempted:

 # ping 192.168.1.54 PING 192.168.1.54 (192.168.1.54) 56(84) bytes of data. --- 192.168.1.54 ping statistics --- 4 packets transmitted, 0 received, 100% packet loss, time 1999ms 

Running tcpdump on any host in the network shows ARP requests with no answers:

 15:34:43.103544 arp who-has 192.168.1.54 tell 192.168.1.18 15:34:44.103292 arp who-has 192.168.1.54 tell 192.168.1.18 15:34:45.102982 arp who-has 192.168.1.54 tell 192.168.1.18 15:34:46.103620 arp who-has 192.168.1.54 tell 192.168.1.18 ... 

The ARP cache lists the host, but has no corresponding MAC address:

 # arp Address                  HWtype  HWaddress           Flags Mask        Iface 192.168.1.54                     (incomplete)                          eth1 192.168.0.20             ether   00:01:02:F7:7C:4B   C                 eth1 

35.1.7. The arpwatch Command

Now that you understand how the arp command works, it is important to understand that you can use ARP to help secure your systems. The arpwatch package is a set of tools that allows your system to monitor ARP mappings on a network. You may need to install the package manually.

Many applications, including ettercap (http://ettercap.sourceforge.net), can engage in ARP spoofing in order to appear to be a different system on your local area network. As you have seen earlier in this chapter, an administrator can also use the ifconfig command on some systems to engage in manual ARP spoofing. ARP spoofing can be a prelude to many attacks, including connection hijacking and traffic sniffing.

The most useful conditions for running arpwatch are when the local area network is connected by a hub or a switch on which monitoring has been enabled. If a system is connected to a standard switch, the switch will not pass ARP traffic and all you can monitor is the traffic between the switch and the system running arpwatch. Similarly, any remote system you want to monitor must be connected to a hub on your network or to a switch on which monitoring has been enabled.

The purpose of arpwatch is to keep an eye on hosts that add themselves to your network and hosts that suddenly change IP address and MAC address mappings.

Once installed, arpwatch runs as a daemon, keeping track of and reporting any changed or new mappings. When a new node appears in the network, arpwatch sends a message to a defined email address to report information on the new host. By default, this email address is the root account. The message is usually sent via the system's email daemon. Sometimes, the messages are also logged to the /var/log/messages or /var/log/syslog file. You can customize arpwatch behavior by editing the /etc/arpwatch.conf file.

arpwatch reports the following problems:

  • Flip-flops, in which the MAC address has changed from one IP address to another

  • A new MAC address

arpwatch is a very useful tool, both as a daemon and as a standalone application, when you are running a network to which no new computers should be connected without the system administrator knowing it.

35.1.7.1. arpwatch

Syntax

 arpwatch [options] 


Description

Report unusual events related to the ARP cache.


Frequently used options


-f file

Specifies which file to use for storing the IP/MAC mappings.


-i interface

Specifies the interface on which to listen for ARP changes.


-m email_address

Sets the email address to which arpwatch should report changes.


-n [network/netmask]

Defines additional IP networks to watch. This is used when two or more different IP networks share the same physical infrastructure.

35.1.7.2. Sample arpwatch results

Once running, arpwatch keeps track of new systems that come on the network. New systems generate a "new station" email message, as shown in Figure 35-1.

Figure 35-1. Viewing an arpwatch "new station" message


Notice in the example that the IP address and MAC address are given, along with the remote host's name name, the remote host's interface name (in this case, eth0), and the NIC's vendor.

Figure 35-2 shows an example of a series of flip-flops brought on by the use of ettercap on a switched network.

Figure 35-2. Flip-flop warnings generated by arpwatch in the /var/log/messages file


The warning shown turned up while sniffing all the packets going between all the local network hosts and a network router with IP address 192.168.2.1. The first entry, for instance, states that a flip-flop has occurred where the system with the IP address of 192.168.2.1 had the original MAC address 00:60:97:75:0E:96, but now has the MAC address 0:b:5d:91:fe:d1. In this case, arpwatch has just discovered a MAC address spoofing attack.

If you look at further entries in Figure 35-2, you will see that several more flip-flops have occurred for the same system. This implies active ARP spoofing from an application. It also suggests that someone on the network is sniffing connections.

35.1.8. Dial-up Connections

Discussing dial-up access has become somewhat controversial in LPI circles. Why? Broadband connections have become more available in many places of the world. More developed countries boast multimegabit connections. I live about 10 miles out of Olympia, Washington, a small town in the Pacific Northwest of the United States. Even though I live fairly far away from a pretty small town, I regularly enjoy an inexpensive 2.5-MBps downstream connection. A few people who enjoy this widespread form of bandwidth have approached me and fellow colleagues at LPI and rather forcefully challenged us as to why the LPI even bothers talking about dial-up connections anymore. The reason is simple: most of the world still uses dial-up. The LPI Exams are published worldwide, and the LPI exams reflect how Linux is used.

Chances are, LPIC 2-certified professionals will at some time find themselves in a dial-up-only environment. Personally, I would be embarrassed if someone handed me a telephone line, and I had to say, "SorryI need an RJ-45. I can't network any other way." As someone who has been associated with the LPI for some time, I would be embarrassed if someone who is LPIC Level 2-certified couldn't use his system properly in a dial-up environment.

So, let's talk about what you need to know to configure a Linux system for dial-up access.

Connecting with dial-up is quite different from connecting to a LAN. A dial-up connection uses the Point-to-Point Protocol (PPP), which effectively runs on a direct link between the user's computer and the ISP. Each side runs a daemon called pppd. When connecting to an ISP through a modem or an ISDN adapter, you need to configure some of the files in /etc/ppp.

Different tools exist to configure dial-up connections: Debian systems offer pppconfig, Slackware systems offer pppsetup, and Fedora systems offer system-config-network-tui (or system-config-network-gui for an X interface). On Red Hat systems, the different configuration tools are called redhat-config instead of Fedora's system-config.

PPP is a Layer 2 protocol for connection over synchronous and asynchronous circuits. Often, connections over analog devices such as modems are asynchrounous, while connections over digital devices such as ISDN adapters are synchronous. Some cable modem and DSL providers also use PPP over Ethernet (for which the PPP frames are encapsulated in Ethernet frames); this protocol is called PPPoE.

Another protocol, Link Control Protocol (LCP), is provided by PPP. This protocol knows how to handle situations such as varying packet sizes and network misconfigurations and is responsible for establishing and terminating the connection. PPP also provides the Network Control Protocol (NCP), which enables the transport of Layer 3 protocols such as IP and IPX. A separate protocol, Password Authentication Protocol (PAP) or the newer Challenge Handshake Authentication Protocol (CHAP), negotiates and sets up the session between the two endpoints.

35.1.8.1. Connecting with a modem

Some distributions include the tools pon (PPP on) and poff (PPP off) to connect to and disconnect from an ISP. A somewhat easier solution is to use the more intelligent wvdial utility, configured through wvdialconf.

For various purposes, you can set up processes to run automatically after taking a PPP line up or down. For instance, a home user with a dial-up connection being enabled at irregular intervals may want to send any outgoing emails and check for any incoming whenever she first comes online. You can add commands and the names of scripts to the files /etc/ppp/ip-up and /etc/ppp/ip-down to run these scripts and commands when the line goes up or down, respectively. On Fedora systems, the user is encouraged to use the files ip-up.local and ip-down.local instead.

While the regular pon command starts the pppd service before dialing the ISP, wvdial connects to the ISP and performs a few basic checks before starting the pppd service.

The following configuration was done on a Debian Linux system, but the files should be the same on most distributions. The system is set up according to the following information received from the ISP, which here we'll simply call provider:

User name: foo

Password: bar

Phone number to dial: 22334455

First, you need to create a file named after the ISP, in this case /etc/ppp/peers/ provider. There should be one file for each ISP you connet to in the /etc/ppp/peers directory. These files hold information on which serial interface the modem is connected to (/dev/ttyS2), the modem speed (115,200 baud), and the username for lookup in the /etc/ppp/chap-secrets file used by CHAP. Each provider-specific file also tells the system how to configure its network; usually the system receives an IP address from the provider and is told to use the dial-up PPP link as its default route. Furthermore, the file tells pppd to run the chat program when connecting. The chat program consults a chat script (a file containing strings that each side is supposed to send) to handle authentication and PPP configuration when connected to the ISP's modem.

35.1.8.2. Configuration files

Some examples follow of files used in dial-up connections . First view the /etc/ppp/peers/provider file:

 hide-password noauth connect "/usr/sbin/chat -v -f /etc/chatscripts/provider" debug /dev/ttyS2 115200 defaultroute noipdefault user "foo" ipparam provider 

The /etc/chatscripts/provider file should be created to match the /etc/peers/provider script file. Because the authentication process changes between ISPs, these scripts need to be specific to each provider. The chat program deals with the authentication process when dialing in to an ISP.

An example follows of the /etc/chatscripts/provider file:

 ABORT BUSY ABORT 'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT 'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED '' ATZ OK-AT-OK "ATDT22334455" CONNECT \d\c 

The different situations that can abort a dial-up are listed in this file. Among the possible reasons for terminating a dial-up attempt are a busy phone line and the lack of a dial tone. The ATZ command is a key command in the Hayes modem control language, which tells the modem to reset. Following that line is the Hayes command for dialing the number to the ISP.

Usernames and passwords for dial-up connections are stored in the file /etc/ppp/chap-secrets when using CHAP authentication. If the ISP prefers PAP authentication, the file to edit is /etc/ppp/pap-secrets. The file format is the same for both CHAP and PAP.

A sample /etc/ppp/chap-secrets file follows. It contains only one noncomment line, whose fields reflect the information shown earlier, given by the ISP:

 # Secrets for authentication using CHAP # client        server  secret                  IP addresses "foo"           *       "bar" 

Because this file contains no IP address, the system we connect to defines our IP address.


Tip: The LPI Exam does not ask you how to use an easy-to-configure application such as pptp-config (http://www.freshmeat.net). It will ask you how to use the command-line application and files discussed previously.
35.1.8.3. pon

pon is a script that eases the somewhat complex argument list pppd often needs to establish a dial-up connection. pon connects to the profile of the provider you give on its command line. The program itself does not produce much output, but pppd (called by pon) creates some entries in the message log, especially when pppd is in debug mode. Following is the syntax for the command:

 pon provider 

The message log tells us that pon successfully established both the dial-up connection and the PPP link:

 Apr 24 18:22:18 foo pppd[1078]: pppd 2.4.2 started by root, uid 0 Apr 24 18:22:19 foo chat[1079]: abort on (BUSY) Apr 24 18:22:19 foo chat[1079]: abort on (NO CARRIER) Apr 24 18:22:19 foo chat[1079]: abort on (VOICE) Apr 24 18:22:19 foo chat[1079]: abort on (NO DIALTONE) Apr 24 18:22:19 foo chat[1079]: abort on (NO DIAL TONE) Apr 24 18:22:19 foo chat[1079]: abort on (NO ANSWER) Apr 24 18:22:19 foo chat[1079]: abort on (DELAYED) Apr 24 18:22:19 foo chat[1079]: send (ATZ^M) Apr 24 18:22:19 foo chat[1079]: expect (OK) Apr 24 18:22:20 foo chat[1079]: ATZ^M^M Apr 24 18:22:20 foo chat[1079]: OK Apr 24 18:22:20 foo chat[1079]:  -- got it Apr 24 18:22:20 foo chat[1079]: send (ATDT22334455^M) Apr 24 18:22:20 foo chat[1079]: expect (CONNECT) Apr 24 18:22:20 foo chat[1079]: ^M Apr 24 18:22:38 foo chat[1079]: ATDT22334455^M^M Apr 24 18:22:38 foo chat[1079]: CONNECT Apr 24 18:22:38 foo chat[1079]:  -- got it Apr 24 18:22:38 foo chat[1079]: send (\d) Apr 24 18:22:39 foo pppd[1078]: Serial connection established. Apr 24 18:22:39 foo pppd[1078]: Using interface ppp0 Apr 24 18:22:39 foo pppd[1078]: Connect: ppp0 <--> /dev/ttyS2 Apr 24 18:22:40 foo pppd[1078]: Remote message: login ok.  welcome to PowerTech Internet. Apr 24 18:22:40 foo pppd[1078]: PAP authentication succeeded Apr 24 18:22:40 foo kernel: PPP BSD Compression module registered Apr 24 18:22:41 foo kernel: PPP Deflate Compression module registered Apr 24 18:22:41 foo pppd[1078]: local  IP address 195.159.185.53 Apr 24 18:22:41 foo pppd[1078]: remote IP address 195.159.0.36 Apr 24 18:22:41 foo pppd[1078]: primary   DNS address 195.159.0.100 Apr 24 18:22:41 foo pppd[1078]: secondary DNS address 195.159.0.200 

The rather long preceding log example shows that the connecting process begins by starting pppd and then calling the chat program. chat talks to the modem, first sending all the ABORT conditions, then sending a modem reset (ATZ). The modem responds by saying OK. Then the modem is told to call the ISP's phone number, expecting a CONNECT from the modem. Upon receiving the CONNECT, pppd resumes control and starts the PPP negotiation. Two kernel modules are loaded in the process, the PPP BSD Compression module and the PPP Deflate Compression module. Finally, the IP addresses of the Point-to-Point Protocol connection are set.

35.1.8.4. Checking a dial-up network connection

You can make sure your system really has an IP connection to the remote system by running ifconfig and route:

 # ifconfig ppp0 ppp0      Link encap:Point-to-Point Protocol           inet addr:195.159.185.53  P-t-P:195.159.0.36  Mask:255.255.255.255           UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1           RX packets:14 errors:0 dropped:0 overruns:0 frame:0           TX packets:14 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:3           RX bytes:2251 (2.1 KiB)  TX bytes:390 (390.0 b) # route -n Kernel IP routing table Destination     Gateway         Genmask         Flags Metric Ref    Use Iface 195.159.0.36    0.0.0.0         255.255.255.255 UH    0      0        0 ppp0 0.0.0.0         195.159.0.36    0.0.0.0         UG    0      0        0 ppp0 

35.1.8.5. The poff command

The syntax for using poff is:

 poff [options] [provider] 

The poff command tears down the PPP connection to the named provider. If more than one ISP is connected, poff needs to know which ISP to disconnect. The most frequently used options are:


-a

Stop all running PPP connections. If the provider argument is given, it is ignored.


-c

Cause pppd to renegotiate compression, which is often useful when servers offer multiple compression protocols.


-r

Cause the connection to be redialed after it is dropped.

35.1.8.6. The wvdial command

wvdial is a curses-based PPP dialer designed to replace the combinations of pppd configuration files and chat scripts. wvdial is built to handle most dial-up situations, and can try PPP commands to enable the connection if the ISP does not automatically enable one.

The syntax for the command is:

     wvdial [options] [section] 

The most frequently used options are:


--chat

Run pppd and use wvdial just to establish the connection, instead of the default behavior of establishing a connection and then starting pppd.


--config [configfile]

Use a different configuration file from the default /etc/wvdial.conf.


--no-syslog

Suppress the debug information normally sent to syslog. Useful only if used with the --chat option.

35.1.8.7. Configuring wvdial: wvdialconf

The wvdialconf command creates the wvdial configuration file. This file is usually located at /etc/wvdial.conf. Invoke wvdialconf as follows:

 wvdialconf config_file 

You can name the file anything you wish, though /etc/wvdial.conf is the standard name and location.

35.1.8.8. wvdialconf examples

Following is the successful execution of wvdialconf:

 # wvdialconf /etc/wvdial.conf Scanning your serial ports for a modem. Port Scan<*1>: Scanning ttyS2 first, /dev/modem is a link to it. ttyS2<*1>: ATQ0 V1 E1 -- OK ttyS2<*1>: ATQ0 V1 E1 Z -- OK ttyS2<*1>: ATQ0 V1 E1 S0=0 -- OK ttyS2<*1>: ATQ0 V1 E1 S0=0 &C1 -- OK ttyS2<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 -- OK ttyS2<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK ttyS2<*1>: Modem Identifier: ATI -- 3361 ttyS2<*1>: Speed 4800: AT -- OK ttyS2<*1>: Speed 9600: AT -- OK ttyS2<*1>: Speed 19200: AT -- OK ttyS2<*1>: Speed 38400: AT -- OK ttyS2<*1>: Speed 57600: AT -- OK ttyS2<*1>: Speed 115200: AT -- OK ttyS2<*1>: Max speed is 115200; that should be safe. ttyS2<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK Found a modem on /dev/ttyS2, using link /dev/modem in config. Modem configuration written to /etc/wvdial.conf. ttyS2<Info>: Speed 115200; init "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0" 

You can then edit the /etc/wvdial.conf file and supply the ISP login details.


Tip: wvdialconf may fail to create a configuration file and complain that no modem can be found. If this is the case, make sure that you have attached the external modem to your serial port and turned it on. If you are using an internal modem, verify that you are not using a Winmodem, which is a low-cost modem that relies on software and the CPU to function properly. Many times, your Linux system does not have the necessary drivers to use a Winmodem device.
35.1.8.9. Sample /etc/wvdial.conf file

An example follows of a standard wvdial.conf file, including the parameters that the user has to enter manually:

 [Dialer Defaults] Modem = /dev/ttyS2 Baud = 115200 Init1 = ATZ Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 ISDN   = 0 Modem Type = Analog Modem Phone = 22334455 Username = foo Password = bar 

With this file, run the wvdial program to establish the PPP link:

 # wvdial --> WvDial: Internet dialer version 1.53 --> Initializing modem. --> Sending: ATZ ATZ OK --> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 OK --> Modem initialized. --> Sending: ATDT22334455 --> Waiting for carrier. ATDT22334455 CONNECT 115200 --> Carrier detected.  Starting PPP immediately. --> Starting pppd at Sat Apr 24 19:42:12 2004 --> pid of pppd: 1961 

Check with ifconfig and route -n to assure yourself that the PPP connection is now up and running.

35.1.8.10. ISDN connections

Connecting to a remote network via an ISDN adapter is more of a black box on Linux. Most distributions supply utilities to set up the ISDN link. To configure an ISDN connection manually, the programs isdnctrl and ipppd are essential. First of all, however, the ISDN adapter must be recognized by the Linux system. This part may require some work. On my system, an old ISDN adapter that uses the hisax module is installed. If I enter:

 modprobe hisax type=3 protocol=2 io=0x180 irq=9 

The kernel responds with these entries in the message log:

 Apr 25 15:02:19 foo kernel: isapnp: Scanning for PnP cards... Apr 25 15:02:19 foo kernel: isapnp: No Plug & Play device found Apr 25 15:02:20 foo kernel: HiSax: Linux Driver for passive ISDN cards Apr 25 15:02:20 foo kernel: HiSax: Version 3.5 (module) Apr 25 15:02:20 foo kernel: HiSax: Layer1 Revision 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: Layer2 Revision 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: TeiMgr Revision 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: Layer3 Revision 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: LinkLayer Revision 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: Certification not verified Apr 25 15:02:20 foo kernel: HiSax: Total 1 card defined Apr 25 15:02:20 foo kernel: HiSax: Card 1 Protocol EDSS1 Id=HiSax (0) Apr 25 15:02:20 foo kernel: HiSax: Teles IO driver Rev. 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: Teles 16.3 config irq:9 isac:0x980  cfg:0xD80 Apr 25 15:02:20 foo kernel: HiSax: hscx A:0x180  hscx B:0x580 Apr 25 15:02:20 foo kernel: Teles3: ISAC version (0): 2086/2186 V1.1 Apr 25 15:02:20 foo kernel: Teles3: HSCX version A: V2.1  B: V2.1 Apr 25 15:02:20 foo kernel: Teles 16.3: IRQ 9 count 0 Apr 25 15:02:20 foo kernel: Teles 16.3: IRQ 9 count 3 Apr 25 15:02:20 foo kernel: HiSax: DSS1 Rev. 1.1.4.1 Apr 25 15:02:20 foo kernel: HiSax: 2 channels added Apr 25 15:02:20 foo kernel: HiSax: MAX_WAITING_CALLS added 

The kernel responds this way because I have told the hisax module that I have a Teles 16.3 card, also known as a type=3 card. I also have told the card that I am using the DSS1 protocol for the ISDN D channel, which is known as type 2 in this situation. Finally, the I/O address is 0x180, and I am using IRQ 9 for the card.

35.1.8.11. The ipppd daemon

The ISDN Point-to-Point Protocol Daemon, ipppd, is a modified version of pppd, designed to provide synchronous PPP connections over ISDN devices. The syntax is:

 ipppd [options] [device] 

Some options override defaults by disabling features; these options start with hyphens. The most frequently used options are:


-bsdcomp

Disable compression. Used when the ISP does not support compression.


defaultroute

Indicates that when the PPP connection is established, it should be the host's default route. If a default route already exists on the system, no action is taken.


-detach

Does not fork and become a background process. Useful when debugging.


device

Defines the device to connect to.


mru number

Sets the Maximum Receive Unit to number. The default is 1500.


noipdefault

Lets the ISP decide the address on the local end of the PPP link.

 user username 

Specifies the username to be used when dialing the ISP. The username must have a corresponding entry in /etc/ppp/pap-secrets.

35.1.8.12. The isdnctrl command

The ISDN control command, isdncrtl, is used to create and delete ISDN network interfaces. It helps create the parameters and phone numbers for dial-in and dial-out. You can also use isdncrtl to list the current parameters of an already configured network interface.

The syntax for the command is:

 isdnctrl action device 

Following are the most often used options:


addif device

Lets isdnctrl control the named device.


addphone device out number

Links the device to the number that goes to the ISP dial-in ISDN pool.


dialmode device [off|manual|auto]

Defines how the device should react to outgoing and incoming connection requests. If set to off, no connection is possible. If set to manual, an outgoing connection can be established only by issuing the command isdnctrl dial device. If set to auto, the device will establish a connection when IP traffic is about to leave the system (or the local network, if your system is configured as an ISDN router).


eaz device number

Adds the dialing system's ISDN number.


encap device syncppp

Configures the device to encapsulate the IP traffic using synchronous PPP.


huptimeout device 120

Set the idle timeout on the device to 120 seconds. When no IP traffic runs through the ISDN adapter for 120 seconds, it will tear down the connection.


l2_prot device hdlc

Indicate that HDLC is the Layer 2 protocol when using ISDN.


l3_prot device trans

Indicate that trans is the Layer 3 protocol when using ISDN. This command is not really necessary, as TRans is the default.


pppbind device number

Link the ISDN device to the PPP device /dev/ipppnumber. This works only for synchronous PPP. The last value must be a number.


secure device on

This is not used when dialing out. When configuring a dial-in service, this may be set to allow specific phone numbers to use the dial-in service.

35.1.8.13. Using isdnctrl

Running the isdnctrl command with real-life parameters results in output such as the following:

 # isdnctrl addif ippp0 ippp0 added # isdnctrl addphone ippp0 out 21405060 # isdnctrl eaz ippp0 33129027 EAZ/MSN for ippp0 is 33129027 # isdnctrl huptimeout ippp0 120 Hangup-Timeout for ippp0 is 120 sec. # isdnctrl secure ippp0 on Security for ippp0 is on # isdnctrl l2_prot ippp0 hdlc Layer-2-Protocol for ippp0 is hdlc # isdnctrl l3_prot ippp0 trans Layer-3-Protocol for ippp0 is trans # isdnctrl encap ippp0 syncppp Encapsulation for ippp0 is syncppp # isdnctrl pppbind ippp0 0 ippp0 bound to 0 # isdnctrl dialmode ippp0 auto 

The ISDN adapter has now been configured to know each detail needed to establish a remote ISDN connection. To link the system's PPP stack into the ISDN system, the ISDN Point-to-Point Protocol Daemon (ipppd) must run:

 # ipppd user foo defaultroute noipdefault -detach mru 1524 \  -bsdcomp /dev/ippp0 & 

This command creates the following log output:

 Apr 25 15:57:12 foo ipppd[599]: Found 1 device: Apr 25 15:57:12 foo ipppd[599]: ipppd i2.2.12 (isdn4linux version of pppd by MH) started Apr 25 15:57:12 foo ipppd[599]: init_unit: 0 Apr 25 15:57:12 foo kernel: ippp, open, slot: 0, minor: 0, state: 0000 Apr 25 15:57:12 foo kernel: ippp_ccp: allocated reset data structure c3966000 Apr 25 15:57:12 foo ipppd[599]: Connect[0]: /dev/ippp0, fd: 7 Because we set the dial mode to auto (by issuing the command isdnctrl dialmode ippp0 auto), the connection will be established on demand and taken down after a specified number of seconds of idle time. This is how to manually activate the ISDN PPP connection: # isdnctrl dial ippp0 Dialing of ippp0 triggered 

Your ISDN connection has now been created. To manually hang up the PPP connection, enter:

 # isdnctrl hangup ippp0     ippp0 hung up 

35.1.8.14. Multihomed systems

Computers with more than one network connection are often referred to as multihomed. Examples of such network connections may be two (or more) Ethernet NICs used to connect a small or home office to a cable or DSL modem. In some situations, you may use one Ethernet NIC for connecting to the LAN and an ISDN adapter to provide Internet access, although this is rare in many countries. No matter what configuration you choose, multihomed systems are increasingly popular. There may be a variety of reasons to use a multihomed host. Most often, however, this configuration is used when a Linux system serves as a router (and usually a firewall as well).

35.1.8.15. IP routing configuration

When configuring a router, one detail must not be forgotten: enable IP routing. This is done by setting the value of /proc/sys/net/ipv4/ip_forward to 1 (one). The system configuration files to enable this routing are /etc/network/options in Debian (set ip_forward=yes) and /etc/sysctl.conf in Fedora (set net.ipv4.ip_forward = 1). When this is enabled, you have a router running. If the nodes on your networks (on both or all sides of the multihomed Linux system) set your system's IP address as their default gateway, they will reach each other, being routed by the Linux host.

The following is a simple way to enable IP forwarding from a command line:

 # sudo echo "1" > /proc/sys/net/ipv4/ip_forward 

You can alternatively configure the /etc/network/options file, changing the ip_forward=no value to ip_forward=yes. You have to be root to accomplish either of these tasks. In a safe and peaceful network environment, this is all that is needed. If you are not in that situation, adding a firewall using iptables is recommended, even on dial-up links. Configuring firewalls is covered by Chapter 40.

35.1.8.16. IP forwarding versus firewalling and Network Address Translation (NAT)

Simply enabling IP forwarding does not create a firewall, nor does it allow you to route private IP addresses to the Internet. Three ranges of IP addresses have been set aside for private networks . These IP addresses are automatically dropped by all Internet routers. Internal routers for your network will pass these IP addresses, however.

The private IP address ranges are:

  • The entire 10.0.0.0 IP address block, with the subnet mask of 255.0.0

  • All IP addresses between 172.16.0.0 and 172.31.255.255,with the subnet mask of 255.240.0.0

  • All IP addresses between 192.168.0.0 and 192.168.255.255, with the subnet mask of 255.255.0.0

In order to route these IP addresses on to the Internet, you need to engage in Network Address Translation. The iptables or ipchains command allows you to do this. iptables is preferred in modern versions of Linux. These commands also allow you to control the packets that pass between multihomed systems, thereby making your router a firewall. See Chapter 40 for more information about using iptables to enable NAT and firewalling.




LPI Linux Certification in a Nutshell
LPI Linux Certification in a Nutshell (In a Nutshell (OReilly))
ISBN: 0596005288
EAN: 2147483647
Year: 2004
Pages: 257

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net