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 網絡模型所示:
層 | 功能 |
---|---|
應用層 | 終端用戶應用程序 |
傳輸層 | 把數據傳送至應用 |
網絡層 | 基本的通信、尋址和路由功能 |
鏈路層 | 網絡硬件和設備驅動程序 |
物理層 | 電纜或者物理介質本身 |
背景知識先放放,具體來看看在 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)接入指南。