1 TCP/IP 协议
这一章节的内容是一章主题性非常强的内容,即使是《Linux Administration Handbook》原书上关于 TCP/IP 协议的叙述也只能是点到即止。因为即使是最基本的连网知识都是一个很大的专题,因此,本文无法也不可能对这些知识进行完全描述,因此我建议看官如果需要了解更多关于 TCP/IP 协议的知识,可以参阅书上所罗列出来的一些书籍进行补充:
- STEVENS, W.RICHARD. UNIX Network Programming. Upper Saddle River, NJ: Pren tice Hall. 1990.
- STEVENS, W.RICHARD. UNIX Network Programming, Volume 1: The Sockets Networking API (3rd Edition). Upper Saddle River, NJ: Prentice Hall. 2003.
- STEVENS, W.RICHARD. UNIX Network Programming, Volume 2: Interprocess Communications (2nd Edition). Upper Saddle River, NJ: Prentice Hall. 1999.
据书上所言,这几本书都是学生上网络编程课的经典教材。因此如果有需要往网络编程方面学习的话,可以阅读这些经典著作。
- TANENBAUM, ANDREW. Computer Networks, (4th Edition). Upper Saddle River, NJ: Prentice Hall. 2003.
这本书是第一本讲网络技术的教科书,也是一本经典书籍,很荣幸地我手头上就有这么一本书,至于是如何,何时得到这么一本好书的,我已经记不起来了,可能是大学的时候同学送的,也有可能是当年在二手书店捞到的,但无论如何,这绝对是一本经典的好书。它非常详细地介绍了协议栈的物理层和链路层的知识。当然,理论性也是非常强的。:)
2 连网技术概述
背景知识:
- TCP (Transmission Control Protocol) 是一种面向连接的协议
- IP (Internet Protocol) 把数据分组从一台计算机路由至另一台计算机的协议
- ARP (Address Resolution Protocol) 将 IP 地址翻译为硬件地址
- UDP (User Datagram Protocol) 是一种无连接协议,它不具有任何形式的拥塞控制
如果光看上面的一句话解释有可能摸不着头脑,如果是这种情况的话可以点击它们上面链接先 wiki 一下。TCP/IP 协议包括 5 层,每一层都有特定的用途,如下表的 TCP/IP 网络模型所示:
层 | 功能 |
---|---|
应用层 | 终端用户应用程序 |
传输层 | 把数据传送至应用 |
网络层 | 基本的通信、寻址和路由功能 |
链路层 | 网络硬件和设备驱动程序 |
物理层 | 电缆或者物理介质本身 |
![](https://img-my.csdn.net/uploads/201301/14/1358141458_9333.png)
背景知识先放放,具体来看看在 Linux 系统上如何将理论应用到实践中去。有时间再去 hack 这些理论知识。
3 将一台主机加入网络
首先需要找到配置文件存放的位置,很不幸地,每个发行版本的网络配置文件所存放的位置都不尽相同。
系统 | 文件 | 设置内容 |
---|---|---|
Red Hat, Fedora | /etc/sysconfig/network | 主机名、默认路由 |
network-scripts/ifcfg-ifname | IP 地址、网络掩码、广播地址 | |
SUSE | /etc/rc.config | 主机名、IP 地址、网络掩码等 |
/etc/route.conf | 默认路由 | |
Debian, Ubuntu | /etc/hostname | 主机名 |
/etc/network/interfaces | IP 地址、网络掩码、默认路由 |
3.1 分配主机名和 IP 地址
把名字映射到 IP 地址的最古老也最简单的方式就是 /etc/hosts 文件。文件中的每一行以一个 IP 地址开头,后面跟着多个不同的符号名,即这个地址已知的名字。下面是一个例子,主机是 lollipop
127.0.0.1 localhost 192.108.21.48 lollipop.xor.com lollipop loghost 192.108.21.254 chimchim-gw.xor.com 192.108.21.1 ns.xor.com ns 192.225.33.5 licenses.xor.com license-server这个文件内容最少的版本只包含前两行。通常, /etc/hosts 文件把 localhost 作为第一行。Debian 和 Ubuntu 的这个文件只包含 127.0.0.1 上的 localhost、127.0.0.1 上的系统主机名、以及一些 IPv6 信息。Red Hat 和 Fedora 的文件包含 localhost 和机器自己,而 SUSE 的包含 localhost 以及 localhost 和几个特殊 IPv6 名字的 IPv6 地址。
3.2 ifconfig: 配置网络接口
一条 ifconfig 命令最常见的形式是:
不带参数的 ifconfig 命令会显示出当前所有已经启用了的网络接口的信息。许多系统都知道 -a 选项意味着“所有接口”,所以ifconfig -a 可以用来找出这个系统上的接口。如果您的系统不支持-a 选项,那么可以试试netstat -i 来找到接口名。
如果需要临时改变系统的网络配置(这在客户机上面很常见,但是如果是服务器,那最好还是请慎重点考虑吧),可以看看以下的例子:
broadcast 128.138.243.191 up
这是一个以太网接口的典型例子。IP 地址和广播地址分别设置为 128.138.243.151 和 128.138.243.191,网络掩码 255.255.255.192。以这种方式设置的网络接口配置在重新启动机器之后就被清除掉了,如果需要使用这些值的话,通常需要编辑一个或多个配置文件来实现这一点。
3.3 route: 配置静态路由
route 命令定义了静态路由,静态路由是自始至终都明确不会改变(您希望如此)的路由表项。您可以用 route 命令增加或删除一条路由。格式为:
route del [-net|-host] target [ netmask Nm] gw gateway
参数 target 可以是一个主机地址 -host, 一个网络地址 -net 或者关键字default. 如果target 是一个网络地址,还应该指定一个网络掩码netmask.
gateway 是应该转发包的那台主机,它必须是与主机处在同一个直接连接的网络上的,意思是主机与 gateway 的主机是以双绞线直接连接起来的处于一个直连的网络上。
route 命令可以配合 ifconfig 进行网络的连通测试。若要检查现有路由,可使用netstat -nr 命令,如果您想要看的是名字而不是数字的话,就使用netstat -r 命令。因为域名查询可能会被打断,所以如果您正在做调试的话,最好还是用数字。
3.4 默认路由
一条默认路由把所有在内核路由表里找不到目的网络的包发送到指定的网关。若要设置默认路由,只需简单地把下列代码行加到启动文件中:
route add default gw gateway-IP-address大多数厂商都让它们的系统从配置文件获得网关 IP 地址,而不是把明确的 IP 地址直接写到启动文件。遗憾的是,对于不同的 Linux 发行版本,本地路由信息加入到启动命令序列的方式各不相同(Linux 标准库 [LSB] 快点儿消除这种不该有的毛病吧!)
系统 | 配置文件 | 变量 |
---|---|---|
Red Hat, Fefora | /etc/sysconfig/network | GATEWAY |
SUSE | /etc/route.conf | 加入一行:default IP-addr mask interface |
Debian, Ubuntu | /etc/network/interfaces | gateway |
3.5 配置 DNS
要把一台主机配置为 DNS 客户机,只需编辑一、两个文件就行了:所有系统都要求修改 /etc/resolv.conf, 有些系统还要求修改“服务开关(service switch)”文件。
/etc/resolv.conf 文件列出了要解析不完全的名字(也就是说,不是全名,如 anchor,而不是 anchor.cs.colorado.edu)应该搜索的 DNS 域和名字服务器的 IP 地址以便查找名字。以下是一个 Ubuntu 系统上的例子:
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN nameserver 202.96.128.166 nameserver 202.96.134.133相信您已经看到注释所言了
gererated by resolvconf(8) 以及 DO NOT EDIT THIS FILE BY HAND – YOUR CHANGES WILL BE OVERWRITTEN, 因此在 Ubuntu 系统上如果需要配置 DNS 应该man resolvconf(8) 一下,在resolvconf 的手册页找到将 dns 添加到/etc/network/interfaces 文件的方法,可以将下面这句话添加到需要配置的网络接口里面去:
dns-nameservers 202.96.128.166 202.96.134.133因此配置后的 /etc/network/interfaces 文件看起来应该类似是这样的:
auto eth0 iface eth0 inet static address 192.168.1.24 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 202.96.128.166 202.96.134.133/etc/resolv.conf 文件正是使用了 /etc/network/interfaces 文件中规定的 dns-nameservers 来配置 DNS。其他系统的 DNS 配置方法也基本上相似, /etc/resolv.conf 文件经常是利用其他的脚本对其进行编辑以达到配置 DNS 的,Fedora 17 的 /etc/resolv.conf 文件开头的注释就是 # Generated by NetworkManager.
4 DHCP: 动态主机配置协议
Linux 主机过去需要手工配置才能加入到一个网络中。不过现代的 Linux 系统基本上只要插上网线,网络就已经通了。主要是因为使用了 DHCP (Dynamic Host Configuration Protocol) 协议。
这个协议可以让一台 DHCP 客户机从中央服务器“租用”各种网络和管理参数,中央服务器得到了授权,可以分配这些参数。对于不使用时就关闭的 PC 和拥有间歇性拨号上网客户的 ISP 而言,这种租用模式尤其方便。在许多情况下,一台 DHCP 服务器只提供基本的网络参数,如 IP 地址、网络掩码、默认网关和域名服务器。客户机必须定期向 DHCP 服务器报告,为租用的参数续约。如果没有续约,最后就会过期,到时 DHCP 就可以自由地将地址分配给其它客户机。租用期是可以配置的,但通常是相当长的时间(数小时或数天)。
4.1 DHCP 软件
Linux 发行版本以前曾带有各种各样不同的 DHCP 服务器和客户机软件。现如今,它们都多少形成了标准,采用 ISC (Internet Software Consortium) 的参考实现。ISC 的 DHCP 服务器使用 DNS 动态更新协议。这个服务器不仅为主机分配 IP 地址和其他连网参数,而且还能用正确的主机名到 IP 地址的映射更新 DNS 数据库。
4.2 DHCP 的工作方式
DHCP 是对 BOOTP 的扩展,它向后兼容 BOOTP,BOOTP 最初的设计目的是为了引导 UNIX 无盘工作站。BOOTP 为客户机提供了 IP 地址、网络掩码、默认网关以及 TFTP 引导信息。DHCP 总结归纳了可以提供的参数,并加上“租用”概念。
4.3 ISC 的 DHCP 服务器
为了配置 DHCP 服务器 dhcpd, 需要编辑来自 /etc/dhcpd 或 /etc/dhcpd3 目录的 dhcpd.conf 样本文件。为了设置 dhcpd.conf 文件,需要下面的信息:
- 由 dhcpd 管理 IP 地址的子网,以及可以发放的地址范围
- 按秒计算的初始和最大的租期
- BOOTP 客户机的配置,如果有的话
- 服务器应该传送给 DHCP 客户机的其他任何选项:网络掩码、默认路由、DNS 域、名字服务器等。
下面是一个支持传送启动镜像(Linux Terminal Server Project)的 dhcpd.conf 文件例子:
#
# Default LTSP dhcpd.conf config file.
#
authoritative;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.30 192.168.1.99;
option domain-name "example.com";
option domain-name-servers 192.168.1.1;
option broadcast-address 192.168.1.255;
option routers 192.168.1.1;
# next-server 192.168.0.1;
# get-lease-hostnames true;
option subnet-mask 255.255.255.0;
option root-path "/opt/ltsp/i386";
if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
filename "/ltsp/i386/pxelinux.0";
} else {
filename "/ltsp/i386/nbi.img";
}
}
关于上面例子的实验内容可见本博客的安装 LTSP 瘦客户端系统。
dhcpd 在 dhcpd.less 文件里记录各项出租事务。它也会通过将这个文件重命名为dhcpd.less~, 再从它在内存中的数据库重新创建dhcpd.less 文件这样的方法定期备份这个文件。如果dhcpd 在这个操作过程中崩溃了,那么可能最后只留下一个dhcpd.less~ 文件。在这种情况下,dhcpd 将拒绝启动,您必须在重新启动之前对这个文件重新命名。不要只建立一个空的dhcpd.less 文件,否则当客户机有两个地址的时候就会产生混乱。
DHCP 客户机实际上并不需要配置。它把每个连接的状态文件保存在目录 /var/lib/dhcp 或者 /var/lib/dhclient 下。这些文件的名字是用它们所描述的接口来命名的。例如,dhclient-eth0.less 文件里包含dhclient 已经给接口eth0 设置的所有连网参数。
5 Linux 的动态重新配置和调整
Linux 有它自己调整内核和连网参数的特殊方式。Linux 没有提供一个普通配置文件供读取来设置这些参数,而是把能调整的每个变量的表示都放在虚拟文件系统 /proc 下。连网变量都在目录 /proc/sys/net/ipv4 下:
cipso_cache_bucket_size ping_group_range tcp_mtu_probing cipso_cache_enable route/ tcp_no_metrics_save cipso_rbm_optfmt rt_cache_rebuild_count tcp_orphan_retries cipso_rbm_strictvalid tcp_abc tcp_reordering conf/ tcp_abort_on_overflow tcp_retrans_collapse icmp_echo_ignore_all tcp_adv_win_scale tcp_retries1 icmp_echo_ignore_broadcasts tcp_allowed_congestion_control tcp_retries2 icmp_errors_use_inbound_ifaddr tcp_app_win tcp_rfc1337 icmp_ignore_bogus_error_responses tcp_available_congestion_control tcp_rmem icmp_ratelimit tcp_base_mss tcp_sack icmp_ratemask tcp_congestion_control tcp_slow_start_after_idle igmp_max_memberships tcp_cookie_size tcp_stdurg igmp_max_msf tcp_dma_copybreak tcp_synack_retries inet_peer_maxttl tcp_dsack tcp_syncookies inet_peer_minttl tcp_ecn tcp_syn_retries inet_peer_threshold tcp_fack tcp_thin_dupack ip_default_ttl tcp_fin_timeout tcp_thin_linear_timeouts ip_dynaddr tcp_frto tcp_timestamps ip_forward tcp_frto_response tcp_tso_win_divisor ipfrag_high_thresh tcp_keepalive_intvl tcp_tw_recycle ipfrag_low_thresh tcp_keepalive_probes tcp_tw_reuse ipfrag_max_dist tcp_keepalive_time tcp_window_scaling ipfrag_secret_interval tcp_low_latency tcp_wmem ipfrag_time tcp_max_orphans tcp_workaround_signed_windows ip_local_port_range tcp_max_ssthresh udp_mem ip_local_reserved_ports tcp_max_syn_backlog udp_rmem_min ip_nonlocal_bind tcp_max_tw_buckets udp_wmem_min ip_no_pmtu_disc tcp_mem xfrm4_gc_thresh neigh/ tcp_moderate_rcvbuf名字里带有 rate 和 max 的变量有许多都可以防止发生 DoS (denial of service) 攻击. conf 子目录包含的变量都是按接口来设置的。它包含子目录 all 和 default, 还有每个接口的一个子目录(包括环回接口)。每个子目录都包含一组相同的文件。
accept_local arp_filter disable_xfrm medium_id secure_redirects accept_redirects arp_ignore force_igmp_version promote_secondaries send_redirects accept_source_route arp_notify forwarding proxy_arp shared_media arp_accept bootp_relay log_martians proxy_arp_pvlan src_valid_mark arp_announce disable_policy mc_forwarding rp_filter tag如果您改动了子目录 all 里的什么地方,那么您的改动会施加到所有的接口上。如果您修改了,比如说子目录 eth0 里的同一个变量,那么只有这个接口才受影响. default 子目录包含原来带有的默认值。
6 PPP: 点对点协议
PPP (Point-to-Point Protocol),它以既可以在最慢的 Internet 链路上使用,又可以在最快的 Internet 链路上使用而著称。有时 PPP 与 DSL 和线缆调制调解器(cable modem)这样的新兴家用技术一同使用。我相信您现在正在使用的就是 PPPoE (PPP over Ethernet) 协议,也就是你家那个 ADSL 拨号网络。因为有路由器的缘故,我非常少直接使用pppoe 来进行网络拨号的,所以关于这部分内容的介绍和配置文章建议直接查看 ADSL(PPPOE)接入指南。