admin 管理员组

文章数量: 887016

系列文章目录

服务器开发系列(一)——计算机硬件
服务器开发系列(二)——Jetson Xavier NX
服务器开发系列(三)——Linux与Windows操作系统基础功能对比

文章目录

  • 系列文章目录
  • 前言
  • 一、网络基础
  • 二、TCP/IP协议族
  • 三、局域网
  • 四、无线网络
  • 五、路由器
    • 静态路由之路由器
    • 动态路由器架设:quagga (zebra + ripd)
  • 六、Linux常用网络命令
    • 网络启动方面类命令:
    • 网络状态监控类命令:
    • 网络故障排查类命令:
  • 七、网络性能优化
  • 八、常见网络安全攻防
    • 单机防火墙示例
  • 九、主要服务器搭建
  • 总结
  • 参考资料

前言

网络功能是Linux服务器开发的重要组成部分,这里基于Linux相关书籍中的知识体系,对Linux系统的网络功能进行了梳理。
这里使用的Linux系统是Ubuntu18.04。

一、网络基础

网络就是几部计算机主机或者是网络打印机之类的接口设备,透过网线或者无线网络技术,将这些主机与设备连接起来,使得数据可以透过网络媒体(网线以及网卡等硬件)来传输的一种方式。
当我们说“网络”时,我们一般指的是使用中间通信基础设施的计算机系统与其他计算机系统的交互。我们重点关注TCP/IP协议和在TCP/IP之上实现的协议,例如HTTP,以及在较小程度上适用于有线(802.3)和无线(802.11)以太网媒体访问控制MAC协议。
Internet是一个管理相当松散的所在,只要你能够使用任何支持TCP/IP技术的硬件与操作系统,并且实际连接上网络后,你就进入Internet的世界。在该世界中,没有任何王法的保护,你的实际数据如果接上Internet,在任何时刻都需要自己保护自己,免得中了流弹而受伤!为甚么说Internet没有王法呢?这是因为Internet仅是提供一个网络的连接接口,所以你只要连上Internet后,全世界都可以任你遨游。不过也因为如此,跨海而来的攻击就成了简单的事件。例如,台湾的法律仅适用台湾地区,但是计算机黑客可以在国外透过Internet对你的主机进行攻击,但台湾法律可管不到其他地区!虽然可以透过很多国际渠道来寻求协助,不过还是很难协助你缉拿凶手。因此在你的主机要连上Internet之前,请先询问自己,是否真的需要连上Internet。
支持上网的不同网络硬件与软件很多,最成功的却是Ethernet与Internet,这不是因为两者的技术比较好,而是因为这两者都被标准支持的缘故!标准真的是个很重要的东西,要感谢这些维护标准的专业组织。当有公司想要开发新的硬件时,它可以参考标准组织所发布与维护的文件资料,透过这些文件数据后,该公司就知道要制作的硬件需要符合哪些标准,同时也知道如何设计这些硬件,让它可以兼容于目前的机器,让使用者不会无所适从。软件也有标准,早期Linux在开发时就是透过了解POSIX这个标准来设计内核的,也使得Linux上面可以执行大多数的标准接口软件!
网络其实是又可爱又麻烦的玩意儿,如果你是网络管理员,那么你必须要了解局域网络内的IP, gateway, netmask等参数,如果还想要连上Internet,那么就得要理解DNS代表的意义为何。如果你的单位想要拥有自己的域名,那么架设DNS服务器则是不可或缺的。总之,要设定网络服务器之前,你得要先理解网络基础就是了
网络联机示意图如下:

①节点node:其主要是具有网络地址IP的设备之称,因此上图示中的一般PC、Linux服务器、ADSL调制解调器与网络打印机等,都可以称为一个node!而中间那个hub集线器因为不具有IP,所以不是节点。
②服务器主机server:就网络联机的方向来说,凡是提供数据以响应给用户的主机,都可以被称为是一部服务器。例如,Yahoo是个WWW服务器,昆山的FTP(http://ftp.ksu.edu.tw/)是个文件服务器等。
③工作站workstation或客户端client:任何可以在计算机网络中输入的设备都可以是工作站,若以联机发起的方向来说,主动发起联机去请求数据的,就可以称为是客户端。例如,一般PC打开浏览器对Yahoo请求新闻数据,一般PC就是客户端。
④网卡(Network Interface Card, NIC):内建或者外插在主机上面的一个设备,主要提供网络联机的硬件,目前大都使用具有RJ-45接头的以太网卡。一般node上都具有一个以上的网卡,以达成网络联机的功能。
⑤网络接口:利用软件设计出来的网络接口,主要提供网络地址IP任务。一张网卡至少可以搭配一个以上的网络接口;而每部主机内部其实都拥有一个内部的网络接口,就是loopback(lo)这个循环测试接口!
⑥网络形态或拓扑topology:各个节点在网络上面的连接方式,一般讲的是物理连接方式。例如上图中显示的是一种被称为星形联机star的方式,主要是透过一个中间连接设备,以放射状的方式连接各个节点的一种形态,这就是一种拓朴。
路由器route或网关gateway:具有两个以上的网络接口,可以连接两个以上不同网段的设备,例如IP分享器就是一个常见的路由器。上面的ADSL调制解调器其实不能算是路由器,因为调制解调器通常视为一个在主机内的网卡设备,我们可以在一般PC上面透过拨号软件,将调制解调器仿真成一张实体网卡ppp,因此不能算是网关设备!
习惯将网络按大小范围可定义为:
局域网(Local Area Network, LAN):节点之间的传输距离较近,例如一栋大楼内或一个学校的校区内。可以使用较为昂贵的联机材料,例如光纤或是高质量网线(CAT6)等。网络速度较快,联机质量较佳且可靠,因此可应用于科学运算的集群式系统、分布式系统、云端负荷分担系统等。
广域网(Wide Area Network, WAN):传输距离较远,例如城市与城市之间的距离,因此使用的联机媒体需要较为便宜的设备,例如经常使用的电话线就是一例。由于线材质量较差,因此网络速度较慢且可靠性较低一些,网络应用方面大多为类似email, FTP, WWW浏览等功能。
看看你家的调制解调器(光猫)后面的插孔,你就能够看到有WAN与LAN的插孔。将全部的LAN串在一起就是一个大型的WAN!但现在也可以使用网速作为一个网络区域范围的评量,高网速的跨市网络也可认为是LAN

OSI七层模型是国际标准化组织ISO和国际电报电话咨询委员会CCITT联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。


整个传送过程我们可以类比为:透过应用程序将数据放入第七层的包裹,再将第七层的包裹放到第六层的包裹内,依序一直放到第一层的最大的包裹内,然后传送出去给接收端。接收端的主机就得由第一个包裹开始,依序将每个包裹拆开,然后一个一个交给对应负责的层来检查,这就是OSI七层协议在阶层定义方面需要注意的特色。包裹表面都会有个重要的信息,这些信息包括有来自哪里、要去哪里、接收者是谁等,而包裹里面才是真正的数据。同样的,在真实的七层协议中,每层都会有自己独特的表头数据header,告知对方这里面的信息是什么,而真正的数据就附在后头!
事实上,OSI七层协议只是一个参考的模型model,目前的网络社会并没有什么很知名的操作系统在使用OSI七层协定的联网程序代码,只是因为OSI所定义的七层协议在解释网络传输时,可以解释的非常棒,因此大家都拿OSI七层协议来做为网络的教学与概念的理解。至于实际的联网程序代码,就交给TCP/IP这个协议!虽然OSI七层协议的架构非常严谨,是学习网络的好材料,但也就是因为太过严谨,因此程序撰写相当不容易,所以造成它在发展上面的困扰。TCP/IP也是使用OSI七层协议的概念,所以同样具有分层的架构,只是将它简化为四层,在结构上面比较没有这么严谨,程序撰写会比较容易些。后来由于email,WWW的流行,造成TCP/IP这个标准为大家所接受,这也造就了目前我们的网络社会!

网络媒体一次传输的数据量是有限的,因此如果要被传输的数据太大时,我们在分层的包装中,就得要将数据先拆开放到不同的包裹中,再给包裹一个序号,好让目的端的主机能够藉由这些序号再重新将数据整合回来!一般来说,因为应用程序与程序员比较有关系,而网络层以下的数据则主要是操作系统提供的,因此我们又将TCP/IP当中的应用层视为使用者层,而底下的三层才是我们主要谈及的网络基础!

具有多层网络协议的结果是,每个协议都使用另一个协议的服务,每个协议都需要在传输数据时将协议头(和/或页脚)添加到数据中,并在接收到数据包时将其删除。这可能会使在协议层之间传递数据缓冲区变得困难,因为每一层都需要找到其特定的协议头在缓冲区内的位置。当然,在层之间复制缓冲区会起作用,但效率会非常低。相反,Linux内核使用套接字缓冲区sk_buffs(struct sk_buff)在协议层和网络设备驱动程序之间传递数据。套接字缓冲区包含指针和长度字段,允许每个协议层通过标准函数操作应用程序数据。
将网络置于内核中有两个主要原因
①如果我们不这样做,一次只有一个进程可以访问网卡。通过使用内核网络堆栈,我们能够运行多个网络应用程序、服务器以及客户端。在用户空间中有效地实现相同的结果是不可能的,因为一个进程不能像操作系统调度程序那样抢占另一个进程。
②此外,还有对传入数据包的控制问题。与其他通常是系统的组成部分并完全由用户控制的外围设备不同,网卡NIC提供来自未知来源的数据。如果我们将网络功能委托给用户空间,那么内核就不能充当传入和传出数据的控制器。

二、TCP/IP协议族

对于TCP/IP协议,在Linux内核中称为inet。这是一整套协议,其中最著名的是IP、TCP和UDP。可以在net/ipv4中找到用于IPv4的代码,在net/ipv6中找到用于IPv6的代码。特别是,IPv4协议在inet_init()中初始化(在linux/net/ipv4/af_inet.c中定义)。该函数使用proto_register()函数(在linux/net/core/sock.c中定义)注册每个内置协议。它将协议添加到活动协议列表中,并且还可以选择分配一个或多个缓存。Linux内核实现了一个缓存内存分配器来保存相同对象的缓存(称为平板)。

IP协议是TCP/IP协议族的动力,它为上层协议提供无状态、无连接、不可靠的服务。无状态stateless是指IP通信双方不同步传输数据的状态信息,因此所有IP数据报的发送、传输和接收都是相互独立、没有上下文关系的。这种服务最大的缺点是无法处理乱序和重复的IP数据报。例如发送端发送出的第N个IP数据报可能比第N+1个IP数据报后到达接收端,而同一个IP数据报也可能经过不同的路径多次到达接收端。在这两种情况下,接收端的IP模块无法检测到乱序和重复,因为这些IP数据报之间没有任何上下文关系。接收端的IP模块只要收到了完整的IP数据报(如果是IP分片的话,IP模块将先执行重组),就将其数据部分(TCP报文段)上交给上层协议。那么从上层协议来看,这些数据就可能是乱序的、重复的。面向连接的协议,例如TCP协议,则能够自己处理乱序的、重复的报文段,它递交给上层协议的内容绝对是有序的、正确的。
注意:HTTP协议是无状态协议。一个浏览器的连续两次网页请求之间没有任何关联,它们将被Web服务器独立地处理。
不可靠是指IP协议不能保证IP数据报准确地到达接收端,它只是承诺尽最大努力best effort。很多种情况都能导致IP数据报发送失败。无论哪种情况,发送端的IP模块一旦检测到IP数据报发送失败,就通知上层协议发送失败,而不会试图重传。因此,使用IP服务的上层协议需要自己实现数据确认、超时重传等机制以达到可靠传输的目的。

IPv4头部中的16位总长度total length字段是指整个IP数据报的长度,以字节为单位,因此IP数据报的最大长度为65535(2^16-1)字节。但由于MTU的限制,长度超过MTU的数据报都将被分片传输,所以实际传输的IP数据报(或分片)的长度都远远没有达到最大值。
IP层传递数据链路层的数据可能是一个完整的IP数据报,也可能是一个IP分片,它们统称为IP分组packet。
IP数据报应该发送至哪个下一跳路由(或者目标机器),以及经过哪个网卡来发送,就是IP路由过程。IP模块实现数据报路由的核心数据结构是路由表。这个表按照数据报的目标IP地址分类,同一类型的IP数据报将被发往相同的下一跳路由器(或者目标机器)。
可以使用命令route查看路由表:


通过命令route或其他工具手工修改路由表,是静态的路由更新方式。对于大型的路由器,它们通常通过BGP(边际网关协议)、RIP(路由信息协议)、OSPF协议等来发现路径,并更新自己的路由表,这种更新方式是动态的、自动的。
不是发送给本机的IP数据报将由数据报转发子模块来处理。路由器都能执行数据报的转发操作,而主机一般只发送和接收数据报,这是因为主机上的/proc/sys/net/ipv4/ip_forward内核参数默认被设置为0,我们可以通过修改它来使能主机的数据报转发功能。
由于IP与端口常常连在一起说明,因此网络寻址常常使用IP:port来说明,例如想要连上鸟哥的网站时,正确的写法是:linux.vbird:80。

网络层另外一个重要的协议是ICMP协议(因特网控制报文协议)。它是IP协议的重要补充,主要用于检测网络连接。ICMP协议使用的报文格式如下图:

需要指出的是,ICMP协议并非严格意义上的网络层协议,因为它使用处于同一层的IP协议提供的服务(一般来说,上层协议使用下层协议提供的服务)。

传输层协议主要有三个:TCP、UDP、SCTP。应用层负责处理应用程序的逻辑。数据链路层、网络层和传输层负责处理网络通信细节,这部分必须既稳定又高效,因此它们都在内核空间中实现。而应用层则在用户空间实现,因为它负责处理众多逻辑,比如文件传输、名称查询和网络管理等。如果应用层也在内核中实现,则会使内核变得非常庞大。当然也有少数服务器程序是在内核中实现的,这样代码就无须再用户空间和内核空间来回切换(主要是数据的复制),极大地提高了工作效率。不过这种代码实现起来较复杂,不够灵活,且不便于移植。
TCP协议是TCP/IP协议族中另一个重要的协议。和IP协议相比,TCP协议更靠近应用层,因此在应用程序中具有更强的可操作性。一些重要的socket选项都和TCP协议相关。
①TCP头部信息。TCP头部信息出现在每个TCP报文段中,用于指定通信的源端端口号、目的端端口号,管理TCP连接,控制两个方向的数据流。
②TCP状态转移过程。TCP连接的任意一端都是一个状态机。在TCP连接从建立到断开的整个过程中,连接两端的状态机将经历不同的状态变迁。理解TCP状态转移对于调试网络应用程序将有很大的帮助。
③TCP数据流。通过分析TCP数据流,我们就可以从网络应用程序外部来了解应用层协议和通信双方交换的应用程序数据,重点关注两种类型的TCP数据流:交互数据流和成块数据流。TCP数据流中有一种特殊的数据,称为紧急数据。
④TCP数据流的控制。为了保证可靠传输和提高网络通信质量,内核需要对TCP数据流进行控制,重点关注两个方面:超时重传和拥塞控制。
TCP协议相对于UDP协议的特点是:面向连接、字节流和可靠传输
使用TCP协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。完成数据交换之后,通信双方都必须断开连接以释放系统资源。
TCP协议的连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服务。而无连接协议UDP则非常适合于广播和多播
当发送端应用程序连续执行多次写操作时,TCP模块先将这些数据放入TCP发送缓冲区中。当TCP模块真正开始发送数据时,发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出。因此,TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系。
当接收端收到一个或多个TCP报文段后,TCP模块将它们携带的应用程序数据按照TCP报文段的序号依次放入TCP接收缓冲区中,并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读出,也可以分多次读取,这取决于用户指定的应用程序读缓冲区的大小。因此,应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间也没有固定的数量关系
发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,这就是字节流的概念:应用程序对数据的发送和接收是没有边界限制的。UDP则不然,UDP通信是不可靠的。发送端应用程序每执行一次写操作,UDP模块就将其封装成一个UDP数据报并发送之。接收端必须及时针对每一个UDP数据报执行读操作(通过recvfrom系统调用),否则就会丢包(这经常发生在较慢的服务器上)。并且如果用户没有指定足够的应用程序缓冲区来读取UDP数据,则UDP数据将被截断。由于应用程序数据放置在IP数据包中,这意味着应用程序消息的大小加上UDP和IP标头不能超过IP数据包的大小。主机协商它们之间通信的最大IP数据包大小;大多数网络支持包含1536字节UDP数据的数据包,但有些限制为512字节UDP数据包。如果你有更大的消息要发送,那么必须将你的消息分成多个UDP数据包,并在接收器处重新组合它们。出于这个原因,UDP的大多数用途都是用于短消息,例如来自分布式传感器的测量。
TCP发送端在发送出一个TCP报文段之后启动定时器,如果在定时时间内未收到应答,它将重发该报文段。
有时候我们希望避免TIME_WAIT状态,因为当程序退出后,我们希望能够立即重启它。但由于处在TIME_WAIT状态的连接还占用着端口,程序将无法启动(直到2MSL超时时间结束)。对客户端程序来说,我们通常不用担心重启问题。因为客户端一般使用系统自动分配的临时端口号来建立连接,而由于随机性,临时端口号一般和程序上一次使用的端口号(还处于TIME_WAIT状态的那个连接使用的端口号)不同,所以客户端程序一般可以立即重启。除非强制客户端使用固定端口号。但如果是服务器主动关闭连接后异常终止,则因为它总是使用同一个知名服务端口号,所以连接的TIME_WAIT状态将导致它不能立即重启。不过我们可以通过socket选项SO_REUSEADDR来强制进程立即使用处于TIME_WAIT状态的连接占用的端口
TCP成块数据流:当传输大量大块数据的时候,发送方会连续发送多个TCP报文段,接收方可以一次确认所有这些报文段。那么发送方在收到上一次确认后,能连续发送多少个TCP报文段呢?这是由接收通告窗口(还需要考虑拥塞窗口)的大小决定的。一个TCP报文的成块数据的长度为16384(见TCP报文段1-16的length值),很显然它小于但接近MSS规定的16396字节。另外一个值得注意的地方是,服务器每发送4个TCP报文段就传送一个PSH标志(tcpdump输出标志P)给客户端,以通知客户端的应用程序尽快读取数据。不过这对服务器来说显然不是必需的,因为它知道客户端的TCP接收缓冲区中还有空闲空间(接收通告窗口大小不为0)。
SO_RCVBUF和SO_SNDBUF选项分别表示TCP接收缓冲区和发送缓冲区的大小。不过当我们用setsockopt来设置TCP的接收缓冲区和发送缓冲区的大小时,系统都会将其值加倍,并且不得小于某个最小值。TCP接收缓冲区的最小值是256字节,而发送缓冲区的最小值是2048字节(不同的系统可能有不同的默认最小值)。系统这样做的目的,主要是确保一个TCP连接拥有足够的空闲缓冲区来处理拥塞(例如快速重传算法就期望TCP接收缓冲区能至少容纳4个大小为SMSS的TCP报文段)。此外,我们可以直接修改内核参数/proc/sys/net/ipv4/tcp_rmem和/proc/sys/net/ipv4/tcp_wmem来强制TCP接收缓冲区和发送缓冲区的大小没有最小值限制
有些传输层协议具有带外OOB数据的概念,用于迅速通告对方本端发生的重要事件。因此,带外数据比普通数据(也称为带内数据)有更高的优先级,它应该总是立即被发送。但实际应用中,带外数据的使用很少见,已知的仅有telnet、ftp等远程非活跃程序。
UDP没有实现带外数据传输,TCP也没有真正的带外数据。不过TCP利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供了一种紧急方式。TCP的紧急方式利用传输普通数据的连接来传输紧急数据。这种紧急数据的含义和带外数据类似,因此将TCP紧急数据称为带外数据。TCP接收端只有在接收到紧急指针标志时才检查紧急指针,然后根据紧急指针所指的位置确定带外数据的位置,并将它读入一个特殊的缓存中。这个缓存只有1字节,称为带外缓存。如果上层应用程序没有及时将带外数据从带外缓存中读出,则后续的带外数据(如果有的话)将覆盖它。
SCTP协议(流控制传输协议)是一种相对较新的传输层协议,它是为了在因特网上传输电话信号而设计的

TCP表头数据的内容
①Source Port & Destination Port (来源端口&目标端口):可以说是TCP封包上最重要的参数!
②Sequence Number (封包序号):由于TCP封包必须要带入IP封包当中,所以如果TCP数据太大时(大于IP封包的容许程度),就得要进行分段。这个Sequence Number就是记录每个封包的序号,可以让收受端重新将TCP的数据组合起来。
③Acknowledge Number (回应序号):为了确认主机端确实有收到我们client端所送出的封包数据,我们client端当然希望能够收到主机方面的响应,那就是这个Acknowledge Number的用途。当client端收到这个确认码时,就能够确定之前传递的封包已经被正确的收下。
④Data Offset (资料补偿):其有个Options字段,其字段长度是非固定的,而为了要确认整个TCP封包的大小,就需要这个标志来说明整个封包区段的起始位置。
⑤Reserved (保留):未使用的保留字段。
⑥Code (Control Flag, 控制标志码):当我们在进行网络联机的时候,必须要说明这个联机的状态,好让接收端了解这个封包的主要动作。这是一个非常重要的句柄!这个字段共有6个bits,分别代表6个句柄,若为1则为启动。
⑦Window (滑动窗口):主要是用来控制封包的流量,可以告知对方目前本身有的缓冲器容量(Receive Buffer) 还可以接收封包。当Window=0时,代表缓冲器已经额满,所以应该要暂停传输数据。Window的单位是byte。
⑧Checksum(确认检查码):当数据要由发送端送出前,会进行一个检验的动作,并将该动作的检验值标注在这个字段上;而接收者收到这个封包之后,会再次的对封包进行验证,并且比对原发送的Checksum值是否相符,如果相符就接受,若不符就会假设该封包已经损毁,进而要求对方重新发送此封包!
⑨Urgent Pointer(紧急资料):这个字段是在Code字段内的URG = 1时才会产生作用。可以告知紧急数据所在的位置。
⑩Options(任意资料):目前此字段仅应用于表示接收端可以接收的最大数据区段容量,若此字段不使用,表示可以使用任意资料区段的大小。这个字段较少使用。
⑪Padding(补足字段):如同IP封包需要有固定的32bits表头一样,Options由于字段为非固定,所以也需要Padding字段来加以补齐才行。同样也是32 bits的整数。
由于是16位,因此目标与来源端口最大可达65535号。一部主机上面那么多服务,我们跟主机进行联机时,主机怎么知道我们要的数据是WWW还是FTP,就是透过端口!服务常用端口号:

利用网络传输数据时需要注意字节序,网络协议使用大端字节序。大端字节序是指一个整数的高位字节(23-31bit)存储在内存的低地址处,低位字节(0-7bit)存储在内存的高地址处。小端字节序则是指整数的高位字节存储在内存的高地址处,而低位字节则存储在内存的低地址处。现代PC大多采用小端字节序,因此小端字节序又被称为主机字节序。
需要指出的是,即使是同一台机器上的两个进程(例如一个由C语言编写,另一个由Java编写)通信,也要考虑字节序的问题(Java虚拟机采用大端字节序)。

简单的TCP服务器系统调用代码将阻塞accept()和read()调用以连接到单个客户端。这意味着它只能为这个客户服务。通常,服务应该能够处理许多客户端请求。select()系统调用select(2)调用使您可以同时监视多个套接字。它指示哪些套接字已准备好读取,哪些套接字已准备好写入,以及哪些套接字已引发异常。虽然select()主要用于网络应用程序,但它适用于绑定到任何类型I/O设备的文件描述符。
select()调用通过循环文件描述符列表来工作。对于每个文件描述符,它调用poll()方法,该方法会将调用者添加到该文件描述符的等待队列中,并返回当前适用于该文件描述符的事件(可读、可写、异常)。poll()方法的实现依赖于对应的设备驱动。
多个服务器进程:fork()和exec()在单核系统上使用select()处理多个客户端可能是一个不错的选择。但是,在具有多核的系统上,我们希望利用可用的并行性来提高服务器性能。一种方法是派生一个子进程来处理每个客户端请求。即使在单线程系统上,这种方法也有一个优势:如果在处理客户端请求的进程中发生致命错误,主服务器进程不会死。如果我们在与主服务器活动相同的代码中处理客户端请求(就像我们使用select()的情况一样),那么客户端代码中的异常将杀死整个服务器进程。虽然基于fork()/exec()的代码在概念上很简单,但由于需要处理僵尸子进程,我们可以使用异步信号处理程序sigchld_handler()来执行此操作,每当子进程退出时都会调用该处理程序。本质上,服务器所做的就是在接受请求时派生一个客户端处理程序。处理程序读取客户端消息,直到遇到换行符,然后打印消息,关闭连接并退出。
处理多个客户端的最后一种机制是使用POSIX线程。该方法与基于fork的服务器非常相似:只要接受请求,服务器就会产生一个客户端处理程序线程。处理程序读取客户端消息,直到遇到换行符,然后打印消息,关闭连接并退出。

我们可以通过/etc/services文件查看所有知名的应用层协议,以及它们都能使用哪些传输层服务
当发送端应用程序使用send(或者write)函数向一个TCP连接写入数据时,内核中的TCP模块首先把这些数据复制到与该连接对应的TCP内核发送缓冲区中,然后TCP模块调用IP模块提供的服务,传递的参数包括TCP头部信息和TCP发送缓冲区中的数据,即TCP报文段。
帧的最大传输单元MTU,即帧最多能携带多少上层协议数据(比如IP数据报),通常受到网络类型的限制。过长的IP数据报可能需要被分片fragment传输。帧才是最终在物理网络上传送的字节序列。由于CSMA/CD机制,在这个机制上面可算出若要侦测碰撞,则帧总数据量最小得要有64bytes,再扣除目的地址、来源地址、检查码(前导码不算)后,就可得到数据量最小得要有46bytes!以太网帧的MTU是1500bytes,因此它携带的IP数据报的数据部分最多是1480bytes(IP头部占用20bytes)。考虑用IP数据报封装一个长度为1481bytes的ICMP报文(包括8bytes的ICMP头部,所以其数据部分长度为1473bytes),则该数据报在使用以太网帧传输时必须被分片。但近来的超高速以太网络媒体有支持Jumbo frame (巨型帧),其能够将帧大小改为9000bytes但如果考虑到整个网络,不建议修改这个数值。这是因为我们的封包总是需要在Internet上面跑的,你无法确认所有的网络媒体都支持那么大的MTU!如果你的9000bytes封包通过一个不支持Jumbo frame的网络媒体时,好一点的话该网络媒体(例如交换机/路由器等)会主动帮你重组而进行传送,差一点的可能就直接回报这个封包无效而丢弃了。所以MTU设定为9000这种事,仅能在内部网络的环境中作业。很多的内部集群cluster就将它们的内部网络环境MTU设定为9000,但是对外的网卡可还是1500!
因为IP协议、ARP、RARP协议都使用帧传输数据,所以帧的头部需要提供某个字段(具体情况取决于帧的类型)来区分它们。以以太网帧为例,它使用2字节的类型字段来标识上层协议。如果主机接收到的以太网帧类型字段的值为0x800,则帧的数据部分为IP数据报,以太网驱动程序就将帧交付给IP模块;若类型字段的值为0x806,则帧的数据部分为ARP请求或应答报文,以太网驱动程序就将帧交付给ARP模块。同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以IP数据报的头部采用16位的协议protocol字段来区分它们。
TCP报文段和UDP数据报则通过其头部中的16位的端口号port number字段来区分上层应用程序。比如DNS协议对应的端口号是53,HTTP协议对应的端口号是80。帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务(例如ARP服务、RARP服务、ICMP服务、应用程序)。这样在顶层目标服务看来,封装和分用似乎没有发生过。

HTTP协议是一种应用层协议,它默认使用的传输层协议是TCP协议。在HTTP通信链上,客户端和目标服务器之间通常存在某些中转代理服务器,它们提供对目标资源的中转访问。一个HTTP请求可能被多个代理服务器转发,后面的服务器称为前面服务器的上游服务器。代理服务器按期使用方式和作用,分为正向代理服务器、反向代理服务器和透明代理服务器
正向代理要求客户端自己设置代理服务器的地址。客户的每次请求都将直接发送到该代理服务器,并由代理服务器来请求目标资源。例如,处于防火墙内的局域网机器要访问Internet,或者要访问一些被屏蔽掉的国外网站,就需要使用正向代理服务器。
反向代理则被设置在服务器端,因而客户端无须进行任何设置。反向代理是指用代理服务器来接收Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从内部服务器上得到的结果返回给客户端。这种情况下,代理服务器对外就表现为一个真实的服务器。各大网站通常分区域设置了多个代理服务器,所以在不同的地方ping同一个域名可能得到不同的IP地址,因为这些IP地址实际上是代理服务器的IP地址。下图显示了正向代理服务器和反向代理服务器在HTTP通信链上的逻辑位置。

正向代理服务器和客户端主机处于同一个逻辑网络中。该逻辑网络可以是一个本地LAN,也可以是一个更大的网络。反向代理服务器和真正的Web服务器也位于同一个逻辑网络中,这通常由提供网站的公司来配置和管理。
透明代理只能设置在网关上。用户访问Internet的数据报必然都经过网关,如果在网关上设置代理,则该代理对用户来说显然是透明的。透明代理可以看作正向代理的一种特殊情况。
代理服务器通常还提供缓存目标资源的功能(可选),这样用户下次访问同一资源时速度将很快。优秀的开源软件squid、varnish都是提供了缓存能力的代理服务器软件,其中squid支持所有代理方式,而varnish仅能用作反向代理。
常见的HTTP请求方法有9种:

这些方法中,HEAD、GET、OPTIONS和TRACE被视为安全的方法,因为它们只是从服务器获得资源或信息,而不对服务器进行任何修改。而POST、PUT、DELETE和PATCH则影响服务器上的资源。另一方面,GET、HEAD、OPTIONS、TRACE、PUT和DELETE等请求方法被认为是等幂的idempotent,即多次连续的、重复的请求和只发送一次该请求具有完全相同的效果。而POST方法则不同,连续多次发送同样一个请求可能进一步影响服务器上的资源。
“http://www.baidu/index.html”是目标资源的URL,其中http是所谓的scheme,表示获取目标资源需要使用的应用层协议,其他常见的scheme还有ftp、rtsp和file等。www.baidu指定资源所在的目标主机,index.html指定资源文件的名称,这里指的是服务器根目录(站点的根目标,而不是服务器的文件系统根目录/)中的索引文件。“HTTP/1.0”表示客户端(wget程序)使用的HTTP版本号是1.0,目前主流HTTP版本是1.1。

HTTP协议是一种无状态的协议,即每个HTTP请求之间没有任何上下文关系。如果服务器处理后续HTTP请求时需要用到前面的HTTP请求的相关信息,客户端必须重传这些信息,这样就导致HTTP请求必须传输更多的数据。
在交互式Web应用程序兴起之后,HTTP协议的这种无状态特性就显得不适应了,因为交互程序通常要承上启下。因此,我们要使用额外的手段来保持HTTP的连接状态,常见的解决方法就是Cookie。Cookie是服务器发送给客户端的特殊信息(通过HTTP应答的头部字段“Set-Cookie”),客户端每次向服务器发送请求的时候都需要带上这些信息(通过HTTP请求的头部字段“Cookie”)。这样服务器就可以区分不同的客户了。基于浏览器的自动登录就是用Cookie实现的。

三、局域网

在局域网络的环境中,我们最常使用的就是以太网。当然在某些超高速网络应用环境中,还可能会用到价格昂贵的光纤信道。只是以太网络因为已标准化,设备设置费用相对低廉,所以一般你会听到什么网线或者是网络媒体,几乎都是使用以太网来架设的环境!只是整个网络世界并非仅有以太网这个硬件接口:

每当传输速度增加时,对网线的要求就更严格,这是因为当传输速度增加时,线材的电磁效应相互干扰会增强,因此在网络线的制作时就得需要特别注意线材的质料以及内部线蕊之间的缠绕情况配置等,以使电子流之间的电磁干扰降到最小,才能使传输速度提升到应有的Gigabit。所以在以太网世界中,如果你想要提升原有的fast ethernet到gigabit ethernet的话,除了网卡需要升级之外,主机与主机之间的网线,以及连接主机线路的集线器/交换机等,都必须要提升到可以支持gigabit速度等级的设备才行!
整个以太网的重心是以太网卡!以太网的传输主要就是网卡对网卡之间的数据传递而已。每张以太网卡出厂时,就会赋予一个独一无二的卡号,就是所谓的MAC (Media Access Control)!理论上网卡卡号是不能修改的,不过某些笔记本电脑的网卡卡号是能够修改的。集线器hub是一种网络共享媒体,想象一下上述环境就像一个十字路口,而集线器就是那个路口。这个路口一次只允许一辆车通过,如果两辆车同时使用这个路口,那么就会发生碰撞的车祸,就是所谓的共享媒体。也就是说,网络共享媒体在单一时间点内,仅能被一部主机所使用。
物理网卡由设备驱动程序管理。设备驱动程序是内核和设备硬件之间的软件接口。在内核方面,它使用低级但标准化的API,因此不同网卡的驱动程序都可以以相同的方式使用。正常的文件操作(读、写等)在应用于驱动程序和网卡之间的交互时没有意义,主要区别在于文件,以及扩展的文件存储设备是被动的,而网络设备主动想要将传入的数据包推向内核。因此网卡中断不是先前内核操作的结果(例如文件操作的情况),而是数据包到达的结果。
目前的主流网卡为使用以太网协议所开发出来的以太网卡Ethernet,因此Linux就称这种网络接口为ethN (N为数字)。基本上的网卡名称会是这样分类的:
①eno1:代表由主板BIOS内建的网卡
②ens1:代表由主板BIOS内建的PCI-E界面的网卡
③enp2s0:代表PCI-E界面的独立网卡,可能有多个插孔,因此会有s0, s1… 的编号
④eth0:如果上述的名称都不适用,就回到原本的预设网卡编号。
网卡之间的传输情况有以下的流程:
①监听媒体使用情况(Carrier Sense):A主机要发送网络封包前,需要先对网络媒体进行监听,确认没有人在使用后,才能够发送出帧frame;
②多点传输(Multiple Access):A主机所送出的数据会被集线器复制一份,然后传送给所有连接到此集线器的主机!也就是说A所送出的数据,B, C, D三部计算机都能够接收的到。但由于目标是D主机,因此B与C会将此帧数据丢弃,而D则会抓下来处理;
③碰撞侦测(Collision Detection):该帧数据附有检测能力,若其他主机例如B计算机也刚好在同时间发送帧数据,那么A与B送出的数据碰撞在一块(出车祸),此时这些帧就是损毁,那么A与B就会各自随机等待一个时间,然后重新透过第一步再传送一次该帧数据。透过上述流程,我们可以知道:只要在B计算机上面安装一套监听软件,这套软件将原本要丢弃的帧数据捉下来分析,并且加以重组,就能够知道原本A所送出的信息了。这也是为什么我们都建议重要数据在因特网上面得加密后再传输!既然共享媒体只有一个主机可以使用,为何大家可以同时上网?共享媒体一次只能被一个主机所使用,那么传输100MB的档案,集线器就得被使用80秒(以10Mbps传输时),在这期间其他人都不能使用吗?不是的,由于标准的帧数据在网卡与其他以太网媒体一次只能传输1500bytes,因此我的100MB档案就得要拆成多个小数据报,然后一个一个的传送。每个数据报传送前都要经过CSMA/CD的机制,所以集线器的使用权是大家抢着用的!即使只有一部主机在使用网络媒体时,那么这部主机在发送每个封包间也都是需要等待一段时间的 (96 bit time)!以太网的MAC帧信息为:

上图中的目的地址与来源地址指的就是网卡卡号(hardware address硬件地址),每张网卡都有一个独一无二的卡号,那个卡号的目的就在这个帧的表头数据使用到!硬件地址最小由00:00:00:00:00:00到FF:FF:FF:FF:FF:FF(16进位法),这6 bytes当中,前3 bytes为厂商的代码,后3 bytes则是该厂商自行设定的装置码。
在Linux当中,你可以使用ifconfig指令来查阅你的网卡MAC。在这个MAC的传送中,它仅在局域网内生效,如果跨过不同的网域,那么来源与目的的硬件地址就会跟着改变,这是因为变成不同网卡之间的交流了,所以卡号当然不同!
由于网卡卡号是跟着网卡走的,并不会因为重装操作系统而改变,所以防火墙软件大多也能够针对网卡来进行抵挡的工作,不过抵挡网卡仅能在局域网内进行而已
现在的以太网卡是可以向下支持的,此时其网速可自动的沟通协调出最高的传输速度!

交换机switch等级非常多,其与集线器最大的差异在于交换机内有一个特别内存,这个内存可以记录每个switch port与其连接的PC的MAC地址。当来自交换机两端的PC要互传数据时,每个帧将直接透过交换机的内存数据传送到目标主机上。所以交换机不是共享媒体,且交换机的每个端口port都具有独立的带宽!
由于电子信号是会衰减的,所以当网线过长导致电子信号衰减严重时,就会导致联机质量的不良,因此连接各个节点的网线长度是有限制的!不过一般来说,现今的以太网CAT5等级的网线大概都可以支持到100米的长度,所以无须担心。但是造成信号衰减的情况并非仅有网线长度而已!如果你的网线折得太严重(例如在门边常常被门挤压导致变形),或者自行压制网线接头,但是接头部分的八蕊线缠绕度不足导致电磁干扰严重,或者是网线放在户外风吹日晒导致脆化的情况等,都会导致电子讯号传递的不良而造成联机质量恶劣,此时常常就会发现偶而可以联机、有时却又无法联机的问题!因此当你需要针对企业内部来架设整体的网络时,注意结构化布线可是很重要的!
所谓的结构化布线指的是将各个网络的组件分别拆开,分别安装与布置到企业内部,则未来想要提升网络硬件等级或者是移动某些网络设备时,只需要更动类似配线盘的机柜处,以及末端的墙上预留孔与主机设备的联机就能够达到目的。例如下面的图示:

光是结构化布线所需要选择的网络媒体与网络线的等级,还有机柜、机架,以及美化与隐藏网络线的材料等等的挑选,以及实际施工所需要注意的事项,还有所有硬件、施工所需要注意的标准规范等,已经可以写满厚厚一本书。如果有需要相关硬件结构化布线的信息,可以参考风信子翻译的《Switch and Fast以太网络》的后半段。

IP封包可以达到65535bytes这么大,在比MAC大的情况下,操作系统会对IP进行拆解。只要知道IP表头里面含有:TTL, Protocol, 来源地址与目标地址也就够了!IP的组成是32bits的数值,也就是由32个0与1组成的一连串数字,不过因为人类对于二进制不怎么熟悉,为了顺应人们对于十进制的依赖性,因此将32bits的IP分成四小段,每段含有8bits,将8bits计算成十进制,并且每一段中间以小数点隔开,那就成了目前大家所熟悉的IP书写模样,如下所示:

前面三组数字(192.168.0) 就是网域号码,最后面一组数字则称为主机号码。至于同一个网域的定义是:在同一个物理网段内,主机的IP具有相同的Net_ID,并且具有独特的Host_ID
什么是物理网段?当所有的主机都使用同一个网络媒体串在一起,这个时候这些主机在实体装置上面其实是联机在一起的,那么就可以称这些主机在同一个物理网段内。同时注意,同一个物理网段内,可以依据不同的IP设定,设定成多个IP网段。
在同一个网段内,Net_ID是不变的,而Host_ID则不可重复,此外Host_ID在二进制的表示法当中,不可同时为0也不可同时为1,因为全为0表示整个网段的地址(Network IP),而全为1表示为广播的地址(Broadcast IP)。例如上面例子中,192.168.0.0 (Host_ID全部为0)以及192.168.0.255 (Host_ID全部为1),不可用来作为网段内主机的IP设定,也就是说,这个网段内可用来设定主机的IP是由192.168.0.1到192.168.0.254。
单位公司内的计算机集群,或者宿舍或家里的所有计算机,都设定在同一个网域内是最方便的,因为如此一来每一部计算机都可以直接透过MAC来进行数据的交流,而不必经由路由器来进行封包的转递。
在IPv4里面只有两种IP类别,分别是:
①Public IP : 公共IP,经由INTERNIC所统一规划的IP,有这种IP才可以连上Internet;
②Private IP : 私有IP或保留IP,不能直接连上Internet的IP,主要用于局域网络内的主机联机规划。早在IPv4规划的时候就担心IP会有不足的情况,而且为了应付某些企业内部的网络设定,于是就有了私有IP (Private IP)的产生。私有IP也分别在A, B, C三个Class当中各保留一段作为私有IP网段,就是:
①Class A:10.0.0.0 - 10.255.255.255
②Class B:172.16.0.0 - 172.31.255.255
③Class C:192.168.0.0 - 192.168.255.255
由于这三段Class的IP是预留使用的,所以并不能直接作为Internet上面的连接之用,不然的话到处就都有相同的IP,网络岂不混乱。所以这三个IP网段就只做为内部私有网域的IP沟通之用。简单的说,它有以下几个限制:
①私有IP的路由信息不能对外散播(只能存在内部网络);
②使用私有IP作为来源或目的地址的封包,不能透过Internet来转送(不然网络会混乱);
③关于私有IP的参考纪录(如DNS),只能限于内部网络使用。如果要将私有IP送上Internet,则设定一个简单的防火墙加上NAT (Network Address Transfer)服务,就可以透过IP伪装来使你的私有IP的计算机也可以连上Internet!主机的IP与相关网域的设定方式主要有
①直接手动设定(static):可以直接向你的网管询问可用的IP相关参数,然后直接编辑配置文件(或使用某些软件功能)来设定你的网络。常见于校园网络的环境中,以及向ISP申请固定IP的联机环境;
②透过拨接取得:向你的ISP申请注册,取得账号密码后,直接拨接到ISP,你的ISP会透过它们自己的设定,让你的操作系统取得正确的网络参数。此时你并不需要手动去编辑与设定相关的网络参数。目前中国大部分都是使用拨接的方式。
③自动取得网络参数(DHCP):在局域网内会有一部主机负责管理所有计算机的网络参数,你的网络启动时就会主动向该服务器要求IP参数,若取得网络相关参数后,你的主机就能够自行设定好所有服务器给你的网络参数。最常使用于企业内部、IP分享器后端、校园网络与宿舍环境,及缆线宽带等联机方式。
怎么将Class A的网段变小?换句话说,如何将网域切的更细,这样就可以分出更多段的区网给大家设定。前面提到IP这个32位的数值中分为网域号码与主机号码,其中Class C的网域号码占了24位,而其实我们还可以将这样的网域切的更细,就是让第一个Host_ID被拿来作为Net_ID,所以整个Net_ID就有25bits,至于Host_ID则减少为7bits。在这样的情况下,原来的一个Class C的网域就可以被切分为两个子域,而每个子域就有256/2 - 2 = 126个可用的IP了。这样一来,就能够将原本的一个网域切为两个较细小的网域,方便分门别类的设计。这就需要通过Netmask (子网掩码),其是用来定义出网域的最重要的一个参数。以192.168.0.0 ~ 192.168.0.255这个网域为例,如下所示,这个IP网段可以分为Net_ID与Host_ID,既然Net_ID是不可变的,就假设它所占据的bits已经被用光了(全部为1),而Host_ID是可变的,就将它想成是保留着(全部为0),所以Netmask的表示就成为:

照这样的记忆方法,A, B, C Class的Netmask表示就成为这样:


我们已经知道Host_ID可以拿来当作Net_ID,那么Net_ID使用了25 bits时,就会如下所示:

一般来说,如果我们知道Network以及Netmask之后,就可以定义出该网域的所有IP。因为由Netmask就可以推算出来Broadcast的IP!因此,我们常常会以Network以及Netmask来表示一个网域,例如这样的写法:

Network/Netmask
192.168.0.0/255.255.255.0
192.168.0.0/24 # 因为Net_ID共有24个bit

Class C共有24 bits的Net_ID,所以就有上面192.168.0.0/24这样的写法。
我们知道Network A(192.168.0.0/24)与Network B(192.168.1.0/24)是不同网段,所以PC01与PC11是不能直接互通数据的。不过PC01与PC11是如何知道他们两个不在同一个网段内?这是透过Net_ID来发现的!当主机想要传送数据时,它主要的参考的是路由表(route table),每部主机都有自己的路由表。让我们来看一看预设的情况下,PC01要如何将数据传送到PC02:
①查询IP封包的目标IP地址:当PC01有IP封包需要传送时,主机会查阅IP封包表头的目标IP地址;
②查询是否位于本机所在的网域之路由设定:PC01主机会分析自己的路由表,当发现目标IP与本机IP的Net_ID相同时(同一网域),则PC01会直接透过区网功能,将数据直接传送给目的地主机;
③查询预设路由(default gateway):这里PC01与PC11并非同一网域,因此PC01会分析路由表当中是否有其他相符合的路由设定,如果没有的话,就直接将该IP封包送到预设网关(default gateway)上去,这里default gateway是Server A这一部;
④送出封包至网关后,不理会封包流向:当IP由PC01送给Server A后,PC01就不理会接下来的工作。而Server A接收到这个封包后,会依据上述的流程,也分析自己的路由信息,然后向后继续传输到正确的目的地主机上头。Gateway/Router:网关/路由器的功能就是在负责不同网域之间的封包转递(IP Forwarding),由于路由器具有IP Forwarding功能,并且具有管理路由的能力,所以可以将来自不同网域之间的封包进行转递。此外,你的主机与你主机设定的网关必定是在同一个网段内!每一部主机都有自己的路由表!观察路由表的指令很简单,就是route:

$ route [-n]
$ route
$ route -n


当我们想要了解某个IP是设定于哪张网卡上时,我们的主机会对整个网域发送ARP封包,对方收到ARP封包后就会回传它的MAC给我们,我们的主机就会知道对方所在的网卡,接下来就能够开始传递数据。如果每次要传送都得要重新来一遍这个ARP协定会很烦,因此当使用ARP协议取得目标IP与它网卡卡号后,就会将该记录写入我们主机的ARP table中(内存内的数据)记录20分钟。
如何取得自己本机的网卡卡号MAC:

$ ifconfig eth0


如何取得本机的ARP表格内的IP/MAC对应数据?可透过arp这个指令:

$ arp -[nd] hostname
$ arp -s hostname(IP) Hardware_address
$ arp -n
$ arp -s 192.168.1.100 01:00:2D:23:A1:0E

四、无线网络

无线网络所需要的硬件:AP、无线网卡。无线基地台 (Wireless Access Point, 简称AP),其实其本身就是个IP分享器,会有两个接口,一个可以与外部的IP做沟通,另外一个则是作为LAN内部其他主机的网关!其他主机上面只要安装了无线网卡,并且顺利连上AP后,自然就可以透过AP来连上Internet。整个传输的情况可以用下图来示意:

如果AP不设定任何联机限制,那任何拥有无线网卡的主机都可以透过这个AP连接上你的LAN,通常我们都会认为LAN是信任网域,所以内部是没有防火墙的,也就是不设防的状态,如果有人拿着笔记本电脑经过你的AP可以接收讯号的范围,那么他就可以轻易的透过你的AP连接上LAN,并且透过你的AP连上Internet,那么当他使用你的AP去攻击别人时,最后被发现的跳板是你的AP,而且你内部主机的数据也很有可能被窃取!
你务必在你的AP上面进行好联机的限制设定,一般可以这样做限制的
①在AP上面使用网卡MAC作为是否可以存取AP的限制:如此一来就只有你允许的网卡才能够存取你的AP。不过这个方法有个问题,当有其他主机想要透过这个AP联机时,你就得要手动的登入AP去进行MAC设定,在经常有变动性装置的环境中 (例如公司行号或学校),这个方法比较麻烦!
②设定你的AP联机加密机制与密钥:设定联机时所需要的验证密钥,这个密钥不但可以在网络联机的数据当中加密,使得即使你的数据被窃听,对方也是仅能得到一堆乱码,同时由于client端也需要知道密钥并且在联机阶段输入密钥,因此也可以被用来限制可联机的用户!
上面两种方法你可以同时设定,这样一来会更安全。
如果你有两部AP在同一个局域网内,当你的无线网卡在上网时,会透过哪一个AP联机出去?其实每部AP都会有一个联机的名字,就是SSID或ESSID,这个SSID可以提供给client端,当client端需要进行无线联机时,它必须说明要利用哪一部AP,那个ESSID就是那时需要输入的数据!在鸟哥的示例中,将其AP设定为vbird_tsai名字,并且给予一个密钥密码,设定的方法如同下图所示:


无线网卡有很多模式,如果选择USB无线网卡,想要知道有没有查找到这张网卡,就得要使用lsusb来检查

$ lsusb


察看模块与相对应的网卡代号:(modinfo与iwconfig)

$ iwconfig


利用iwlist侦测AP:首先要启动无线网卡,利用ifconfig即可:

$ ifconfig ra0 up


使用iwlist来使用这个无线网卡搜寻:

$ iwlist ra0 scan


从上面可以看到:
①这个无线AP的协议,
②ESSID的名号是没错的,
③加密的机制是WPA2-PSK也是能够得知的,
④使用的无线频道是6号。
接下来要去修改配置文件,这部份很麻烦,请参考如下的网页来设定:
https://wiki.archlinux/index.php/Rt2870

$ ifconfig ra0 down && rmmod rt3070sta
$ vim /etc/wireless/RT2870STA/RT2878STA.dat
$ modprobe rt3070sta && ifconfig ra0 up
$ lwconfig ra0


如果顺利出现上面的数据,就表示你的无线网卡已经与AP接上线了。
设定网络卡配置文件(ifcfg-ethn)

$ cd /etc/sysconfig/network-scripts
$ vim ifcfg-ra0


要注意的是ONBOOT=no的设定,如果你想要每次开机时无线网卡都会自动启动,那就将它设定为yes!
启动与观察无线网卡

$ ifup ra0


为了在LAN中方便的连接其他主机,可将你的私有IP计算机与计算机名称写入你的/etc/hosts当中:

$ cat /etc/hosts


注意,你的default gateway应该只有一个,如果是拨接,请不要在ifcfg-eth0当中指定GATEWAY或GATEWAYDEV等变量!

五、路由器

路由最大的功能就是帮我们规划网络封包的传递方式与方向。每一部主机都有自己的路由表,你必须透过自己的路由表来传递你主机的封包到下一个路由器上头。若传送出去后,该封包就得要透过下一个路由器的路由表来传送了,此时与你自己主机的路由表就没有关系啦!自己主机的路由表可由以下来说明:

$ route -n


Linux系统下的路由表是由小网域排列到大网域,例如上面的路由表中,路由是由192.168.1.0/24 --> 169.254.0.0/16 --> 0.0.0.0/0 (预设路由)来排列的。其实路由表主要由以下几种情况来设计:
①依据网络接口产生的IP而存在的路由:例如192.168.1.0/24这个路由的存在是由于鸟哥的主机上面拥有192.168.1.100这个IP的关系!主机上面有几个网口存在时,该网口就会存在一个路由。所以你的主机有两个网口时,例如192.168.1.100, 192.168.2.100时,那路由至少就会有192.168.1.0,192.168.2.0。
②手动或预设路由(default route):可以使用route指令手动的给予额外的路由设定,例如上面预设路由0.0.0.0/0就是额外的路由。使用route这个指令时,最重要的一个概念是:你所规划的路由必须要是你的装置(如eth0)或IP可以直接沟通broadcast的情况才行。例如,我的环境里面仅有192.168.1.100及192.168.2.100,那如果想要连接到192.168.5.254这个路由器时,就得下达:

$ route add -net 192.168.5.0 netmask 255.255.255.0 dev eth0
$ route -n


上面路由输出的重点其实是那个“Flags的G”!因为那个G代表使用外部装置作为Gateway的意思。而那个Gateway (192.168.1.254) 必须要在我们已存在的路由环境中。
③动态路由的学习:其需要额外的软件支持,例如zebra或Quagga。
Linux中的路由规则都是透过内核来达成的,所以这些路由表的规则都是在内核功能内,也就是在内存当中!

可以利用两张网卡,利用两个相同网域的IP来增加我这部主机的网络流量,不过必须要透过带宽负载平衡来设定。如果只是单纯的以为设定两张网卡的IP在同一个网域,就能够实现你主机的两倍流量,那就大错特错了。如果你有两张网卡时,假设:
eth0 : 192.168.0.100
eth1 : 192.168.0.200
你的路由规则理论上会变成这样:

$ route -n


也就是说:
①当要主动发送封包到192.168.0.0/24的网域时,都只会透过第一条规则,也就是透过eth1来传出去!
②在响应封包方面,不管是由eth0还是由eth1进来的网络封包,都会透过eth1来回传!这可能会造成一些问题,尤其是一些防火墙的规则方面,很可能会发生一些严重的错误,如此一来根本没有办法达成负载平衡,也不会有增加网络流量的效果!更惨的是,还可能发生封包传递错误的情况!所以同一部主机上面设定相同网域的IP时,得要特别留意你的路由规则,一般来说不应该设定同一网段的不同IP在同一部主机上面。上面的案例就是一个不好的示范!
路由器的主要功能是转递网络封包。也就是说,路由器会分析来源端封包的IP表头,在表头内找出要送达目标IP后,透过路由器本身的路由表 (routing table) 来将这个封包向下一个目标(next hop)传送。
Linux系统可通过打开内核的封包转递(IP forward)功能,来连接两个不同的网域

$ cat /proc/sys/net/ipv4/ip_forward

$ vim /etc/sysctl.conf
# 将底下这个设定值修改正确即可 本来值为0 将它改为1即可
net.ipv4.ip_forward = 1
$ sysctl -p # 立刻让该设置生效


NAT,Network Address Translation,即网络地址转换服务器。NAT可以达成IP分享的功能,而NAT本身就是一个路由器,只是NAT比路由器多了一个IP转换的功能。一般来说,路由器会有两个网口,透过路由器本身的IP转递功能让两个网域可以互相沟通网络封包。如果两个接口一边是公共IP,另一边是私有IP,由于私有IP不能直接与公共IP沟通其路由信息,此时就得要额外的“IP转译”功能了。Linux的NAT服务器可以透过修改封包的IP表头数据来源或目标IP,让来自私有IP的封包可以转成NAT服务器的公共IP,就可以连上Internet!当路由器两端的网域分别是Public与Private IP时,才需要NAT的功能!
一般来说,计算机数量小于数十部的小型企业是无需路由器的,只需要利用hub/switch串接各部计算机,然后透过单一线路连接到Internet上即可。不过,如果是超过数百部计算机的大型企业环境,由于它们的环境通常需要考虑如下状况,因此才需要路由器的架设:
①实体线路之布线及效能的考虑;
②部门独立与保护数据的考虑。

静态路由之路由器


以上图的架构来说,这家公司主要有两个class C网段,分别是:
①一般区网(192.168.1.0/24) :包括Router A, workstation以及Linux Router三部主机所构成;
②保护内网(192.168.100.0/24):包括Linux Router, clientlinux, winxp, win7等主机所构成。
其中192.168.1.0/24是用来做为一般员工连接因特网用的,至于192.168.100.0/24则是给特殊的部门用的。workstation代表的是一般员工的计算机,clientlinux及winxp, win7则是特殊部门的工作用计算机,Linux Router则是这个特殊部门用来连接到公司内部网域的路由器。在这样的架构下,该特殊部门的封包就能够与公司其他部门作实体的分隔了。只要是具有路由器功能的设备(Router A, Linux Router)都会具有两个以上的网口,分别用来沟通不同的网域,同时该路由器也都会具有一个预设路由!你还可以加上一些防火墙的软件在Linux Router上,以保护clientlinux, winxp, win7。
①如果clientlinux想要连上Internet,那么它的联机情况是:
<1>发起联机需求:clientlinux --> Linux Router --> Router A --> Internet
<2>响应联机需求:Internet --> Router A --> Linux Router --> clientlinux
观察一下两部Router的设定,要达到上述功能则Router A必须要有两个接口,一个是对外的Public IP,一个则是对内的Private IP,因为IP的类别不同,因此Router A还需要额外增加NAT机制才行。除此之外Router A并不需要什么额外的设定。至于Linux Router就更简单了,什么事都不用作,将两个网卡设定两个IP,并且启动内核的封包转递功能,立刻就架设完毕了!
②Linux Router在这部主机内需要有两张网卡,鸟哥这里将它定义为:
eth0: 192.168.1.100/24
eth1: 192.168.100.254/24

# 看看eth0的设定
$ vim /etc/sysconfig/network-scrripts/ifcfg-eth0
DEVICE="eth0"
HWADDR="08:00:27:71:85:BD"
NM_CONTROLLED="no"
ONBOOT="yes"
BOOTPROTO="none"
IPADDR=192.168.1.100
NETMASK=255.255.255.0
GATEWAY=192.168.1.254 # 最重要的设定 透过这部主机连出去
 
# 再处理eth1这张之前一直都没有驱动的网卡
$ vim /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE="eth1"
HWADDR="08:00:27:2A:30:14"
NM_CONTROLLED="no"
ONBOOT="yes"
BOOTPROTO="none"
IPADDR=192.168.100.254 

# 启动IP转速 真的实战成功才行
$ vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
# 找到上述的设定值 将默认值0改为上述的1 储存后离开
$ sysctl -p
$ cat /proc/sys/net/ipv4/ip_forward

# 重新启动网络 并观察路由与ping Router A
$ /etc/init.d/network restart
$ route -n


透过最后的ping,我们也知道Linux Router可以连上Router A!这样你的Linux Router就OK了!此外,Linux默认的防火墙规则会将来自不同网卡的沟通封包剔除,所以还得要暂时关闭防火墙才行
③受保护的网域,以clientlinux为例,不论你的clientlinux是哪一种操作系统,其环境都应该是这样的:
IP: 192.168.100.10
netmask: 255.255.255.0
gateway: 192.168.100.254
hostname: clientlinux.centos.vbird
DNS: 168.95.1.1以Linux操作系统为例,并且clientlinux仅有eth0一张网卡时,它的设定是这样的:

$ vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
NM_CONTROLLED="no"
ONBOOT="yes"
BOOTPROTO=none
IPADDR=192.168.100.10
NETMASK=255.255.255.0
GATEWAY=192.168.100.254 # 这个设定最重要
DNS1=168.95.1.1 # 有这个就不用自己改/etc/resolv.conf

$ /etc/init.d/network restart
$ route -n
# ping -c 2 192.168.100.254 # ping自己的gateway(会成功)
# ping -c 2 192.168.1.254 # ping外部的gateway(会失败)


从刚刚的响应联机需求流程来看一下:
<1>发起联机:clientlinux --> Linux Router (OK) --> Router A (OK)
<2>回应联机:Router A (此时router A要响应的目标是192.168.100.10),Router A仅有public与192.168.1.0/24的路由,所以该封包会由public界面再传出去,因此封包就回不来了…需要告知Router A当路由规则碰到192.168.100.0/24时,要将该封包传192.168.1.100就是了。
④特别的路由规则:Router A所需路由:假设Router A对外的网卡为eth1,而内部的192.168.1.254则是设定在eth0上。直接使用route add在Router A上增加一条路由规则即可!

$ route add -net 192.168.100.0 netmask 255.255.255.0 gw 192.168.1.100


不过这个规则并不会写入到配置文件,因此下次重新启动这个规则就不见了!所以应该要建立一个路由配置文件。由于这个路由是依附在eth0网卡上的,所以配置文件的档名应该是route-eth0!这个配置文件的内容当中,我们要设定192.168.100.0/24这个网域的网关为192.168.1.100,且透过eth0,那么写法就会变成:

$ vim /etc/sysconfig/network-scripts/route-eth0
$ route -n


现在内部保护网络已经可以连上Internet了!
那clientlinux可以直接与一般员工的网域,例如workstation进行联机,它的联机方向是这样的:
<1>联机发起:clientlinux --> Linux Router (OK) --> workstation (OK)
<2>回应联机:workstation (联机目标为192.168.100.10,因为并没有该路由规则,因此联机丢给default gateway,亦即是Router A) --> Router A (OK) --> Linux Router (OK) -->clientlinux。
联机发起是没有问题,不过响应联机竟然会偷偷透过Router A来帮忙!这是因为workstation与当初的Router A一样,并不知道192.168.100.0/24在192.168.1.100里面。不过反正Router A已经知道了该网域在Linux Router内,所以该封包还是可以顺利的回到clientlinux。
⑤让workstation与clientlinux不透过Router A的沟通方式:如果不想让workstation得要透过Router A才能联机到clientlinux的话,就得要与Router A相同,增加那一条路由规则!如果是Linux的系统,那么workstation的设定如下:

$ vim /etc/sysconfig/network-scripts/route-eth0
$ /etc/init.d/network restart
$ route -n


透过这样的设定方式,你可以发现:路由是双向的,必须要了解出去的路由与回来时的规则

动态路由器架设:quagga (zebra + ripd)

使用静态路由的方法总是很讨厌,如果某天因为组织的再造导致需要重新规划子网网段,如此一来,你就得要在Router A与Linux Router再次处理与检查路由规则,非常麻烦。但可以通过动态路由来达成自动增加该笔路由的信息。动态路由通常是用在路由器与路由器之间的沟通,所以要让你的路由器具有动态路由功能,必须要了解到对方路由器上面所提供的动态路由协议才行,这样两部路由器才能够透过该协议来沟通彼此的路由规则。目前常见的动态路由协议有:RIPv1, RIPv2, OSPF, BGP等。想要在Linux上面搞定动态路由的相关机制,就得使用quagga这个软件,其是zebra计划的延伸

$ apt install quagga
$ ls -l /etc/quagga


不论你要启动什么动态路由协议,zebra都必须要先启动才行,这是因为:
①zebra这个daemon的功能在更新内核的路由规则;
②RIP这个daemon则是在向附近的其他Router沟通协调路由规则的传送与否。
而各个路由服务的配置文件都必须要以/etc/quagga/*.conf的档名来储存才行,我们可以发现zebra这个服务是有设定好,不过ripd的档名却不是.conf结尾,所以我们必须要额外做些设定才行:

上图的两部Linux Router分别负责不同的网域,其中Router Z1是上个小节设定好之后就保留的,左边的Router Z2则是需要额外设定的路由器!两部Router可以透过192.168.1.0/24这个网域来沟通。在没有设定额外路由规则的情况下,PC Z1与PC Z2是无法沟通的。另外,quagga必须要同时安装在两部Linux Router上才行,而且我们只要设定好这两部主机的网络接口(eth0, eth1)后,不需要手动输入额外的路由设定!可以透过RIP这个路由协议来搞定的:①将所有主机的IP设定妥当:将四部主机(Router Z1, Router Z2, PC Z1, PC Z2)的网络参数按照上图的模式设置妥当。在Router Z1, Z2的部分还得加上修改ipforwrad参数,即是/etc/sysctl.conf的设定值!
②在两部Router上面设定zebra:先设定Router Z1,关于zebra.conf可以这样设定:

# 先设定会影响动态路由服务的zebra并且启动zebra
$ vim /etc/quagga/zebra.conf
hostname www.centos.vbird # 给予这个路由器一个主机名 随便取
password linuxz1 # 给予一个密码
enable password linuxz1 # 将这个密码生效
log file /var/log/quagga/zebra.log # 将所有zebra产生的信息存到登录文档中。
$ vim /etc/quagga/zebra.conf
hostname www.centos.vbird # 给予这个路由器一个主机名 随便取
password linuxz1 # 给予一个密码
enable password linuxz1 # 将这个密码生效
log file /var/log/quagga/zebra.log # 将所有zebra产生的信息存到登录文件中

$ /etc/init.d/zebra start
$ chkconfig zebra on
$ netstat -tunlp; grep zebra


由于zebra这个服务的任务主要是在修改Linux系统内核的路由,所以它仅监听本机接口,并不会监听外部的接口!另外在zebra.conf这个档案当中,我们所设定的那个密码是有作用的,可以让我们登入zebra软件。我们来查一查2601的port是否正确的启动:

$ telnet localhost 2601


如果想要增加额外的静态路由的话,可以透过zebra而不必使用route指令!例如想要增加10.0.0.0/24给eth0的话,可以这样做:

$ vim /etc/quagga/zebra.conf
# 新增底下这一行
ip route 10.0.0.0/24 eth0

$ /etc/init.d/zebra restart
$ telnet localhost 2601


设定完右边Router Z1的zebra之后,不要忘记设定Router Z2,同样的设定再来一遍!只是主机名与密码应该给予不同才是。
③在两部Router上面设定ripd服务:ripd服务可以在两部Router之间进行路由规则的交换与沟通,如果你的环境里面有类似Cisco或者是其他有提供RIP协议的路由器的话,那么你当然也可以透过这个RIP让你的Linux Router与其他硬件路由器互相沟通。只不过Linux的quagga所提供的ripd服务使用的是RIPv2版本。这个版本预设要求得进行身份验证,但我们是小型网络,并不想加入身份验证功能,因此就得要增加某些设定值才能够顺利的启动ripd。先来设定Router Z1,在Router Z1当中,我们主要是透过eth0发送所有的网域路由信息,同时我们管理的网域有192.168.1.0/24, 192.168.100.0/24。再加上取消身份验证的设定值后,我们的ripd就会变成这样:

$ vim /etc/quagga/ripd.conf
hostname www.centos.vbird # 这里是设定Router的主机名而已
password linuxz1 # 设定好自己的密码
debug rip events # 可以记录较多的错误信息
debug rip packet # 鸟哥透过这个信息解决很多问题
router rip # 启动Router的rip功能
  version 2 # 启动的是RIPv2的服务(默认值)
  network 192.168.1.0/24 # 这两个就是我们管理的接口
  network 192.168.100.0/24
  ; no ip rip authentication mode;
log file /var/log/quagga/zebra.log
$ /etc/init.d/ripd start
$ chkconfig ripd on
$ netstat -tulnp; grep ripd


这样就设定完成一部路由器的RIP动态路由协议了。在上头ripd.conf的设定当中,它会主动以eth0及192.168.1.0/24这个网域的功能来进行搜索,如此一来,未来进行任何路由规则的变动,或者是整个网域的主机IP进行更动,将不需要重新到每部Router上更动!因为这些路由器会自动的更新它们自己的规则,同样的动作在Router Z2上设定一下!
④检查RIP协议的沟通结果:在两部Linux Router都设定妥当之后,可以登入zebra去看这两部主机的路由更新结果。例如,鸟哥登入Router Z1后,并且登入zebra,观察路由会是这样的情况:

$ route -n
$ telnet localhost 2601


上图最左边的R代表是透过RIP通讯协议所设定的路由规则。如此一来,路由器设定就搞定。如果一切都没有问题,你也想要开机就启动zebra, ripd,还得要这样:

$ chkconfig zebra on
$ chkconfig ripd on


透过quagga以及RIPv2路由协议的辅助,比起单纯使用route去修改Linux的核心路由表要快速很多!不过如果是很小型的网络环境,那么不要使用quagga,因为有点多此一举的感觉。如果你的企业环境真的够大,那么玩一玩quagga配合一些动态路由协议是可行的。
特殊状况:路由器两边界面是同一个IP网段:ARP Proxy。如果一开始设计的网络环境就是同一个Class C的网域,例如192.168.1.0/24,后来因为某些因素必须要将某些主机搬到比较内部的环境中,例如clientlinxu, winxp, win7。然后又因为某些因素你不能变更这些计算机的IP,此时你的同一网域就会横跨在一个路由器的左右两边!例如,联机图示如下:

如果两块网卡上面都是同一个网域的IP时就会发生错误。先从两方面来说,第一个,当从正确的网段PC1要联机到PC2-PC4时,它应该是透过Linux Router那部主机的对外IP(192.168.1.100)才行。而且Linux Router还必须要让该封包透过内部IP (192.168.1.200)联机到PC2~PC4。此时封包传递的图示有点像这样:

在这个阶段,我们可以设定PC2-PC4的IP所对应的网卡卡号MAC都设定在router的对外网卡上,因此router的对外接口可以将给PC2~PC4的封包给骗过来。接下来就简单的透过路由设定,让封包转个接口发送出去即可,这样PC1 --> PC2的问题解决了,但当PC2要传送的封包是给PC3, PC4的,那么这个封包得要能够直接传递。但是如果需要传送到正常网域的封包,就得要透过router的对内网卡,再透过路由规则来将该封包导向外部接口来传递才行!这个时候就变成内部的接口欺骗PC2,PC1与Router A的IP是在内部这接口上,然后再透过路由判断将该封包透过外部接口来对外传递出去即可。假设Linux router的对外界面为eth0而对内为eth1时,我们可以这样说:
<1>当Linux Router的eth0那个网域主机想要连接到PC2~PC4的主机时,由Linux Router负责接收;
<2>当Linux Router要传送数据到PC2~PC4时,务必要由eth1来传送;
<3>当内部计算机想要连接到PC1或Router A时,由Linux router的eth1负责接收;
<4>当Linux Router要传送的数据为192.168.1.0/24,但并非PC2~PC4时,需由eth0传送。
其中的<1>与<3>就是透过ARP Proxy (代理)的功能!ARP Proxy简单的说就是让某张网卡的MAC代理其他主机的IP对应,让想要连接到这个IP的MAC封包由我帮它接下来的意思。例如,就是在Linux Router的eth0界面上,规定192.168.1.10, 192.168.1.20, 192.168.1.30这三个IP都对应到eth0的MAC上,所以三个IP的封包就会由eth0代为收下,因此才叫做ARP代理!所以每一部在eth0端的主机都会误判那三个IP是Linux Router所拥有,这样就能够让封包传给Linux Router!接下来,Linux Router必须要额外指定路由,设定情况为:
<1>若目标是PC2 ~ PC4时,该路由必须要由内部的eth1发送出去才行,
<2>若目标不为PC2 ~ PC4,且目标在192.168.1.0/24的网域时,需由eth0发送出去才行。
也就是说,你必须要指定路由规则当中那个PC2~PC4具有优先选择权,然后其他的同网域封包才由eth0来传送。这样就能够达成我们所想要的结局!其实设定挺简单,可以透过arp以及route这两个指令来达成:
<1>外部接口eth0:08:00:27:71:85:BD
<2>内部接口eth1:08:00:27:2A:30:14

# 1. 先设定外部eth0的ARP Proxy 让三个IP对应到自己的MAC
$ arp -i eth0 -s 192.168.1.10 08:00:27:71:85:BD MAC
$ arp -i eth0 -s 192.168.1.20 08:00:27:71:85:BD MAC
$ arp -i eth0 -s 192.168.1.30 08:00:27:71:85:BD MAC
$ arp -n

# 2. 开始处理路由 增加PC2-PC4的单机路由经过内部的eth1来传递
$ route add -host 192.168.1.10 eth1
$ route add -host 192.168.1.20 eth1
$ route add -host 192.168.1.30 eth1
$ route -n

# 设定一下内部的ARP Proxy工作(在eth1上)
$ arp -i eth1 -s 192.168.1.101 08:00:27:2A:30:14 pub
$ arp -i eth1 -s 192.168.1.254 08:00:27:2A:30:14 pub
# 这样就处理好单向的单机路由了
# 不过有个问题 192.168.1.0/24的网域 两个接口都可以传递
# 因此下面需要将eht1删除才行

# 设定一下内部的ARP Proxy工作(在eth1上)
$ arp -i eth1 -s 192.168.1.101 08:00:27:2A:30:14 pub
$ arp -i eth1 -s 192.168.1.254 08:00:27:2A:30:14 pub
# 这样就可以骗过PC2 - PC4 让这三部主机传递的封包可以透过router来传递

# 开始清除掉eth1的192.168.1.0/24路由
$ route del -net 192.168.1.0 netmask 255.255.255.0 eth1


所有的计算机都在同一个网域内,因此default gatway都是192.168.1.254,而netmask都是255.255.255.0,只有IP不一样而已。最后所有的计算机都可以直接跟对方联机,也能够顺利的连上Internet,这样的设定就能够满足上述的功能需求!
透过这个案例可以清楚的知道,能不能联机其实与路由的关系更大!而路由是双向的,必须要考虑到这个封包如何回来的问题

六、Linux常用网络命令

要从命令行配置网络,可以使用名为interfaces的配置文件,它的完整路径是/etc/network/interfaces。当系统启动和启用网络接口时,将读取此文件。可以使用nano或其他文本编辑器对此文件进行更改。在撰写本文时,接口文件的配置如下图:

source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback
ifact eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


有时可能需要手动分配自己的IP地址和其他配置信息。下图显示了如何更改接口配置文件以分配静态IP地址信息:

source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

# iface eth0 inet manual
iface eth0 inet static
    address 192.168.0.100
    netmask 255.255.255.0
    gateway 192.168.0.1
    dns-nameservers 8.8.8.8.8.8.4.4

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


如果要使用WiFi,则需要对wlan0部分进行修改:

source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

# iface eth0 inet manual
iface eth0 inet static
    address 192.168.0.100
    netmask 255.255.255.0
    gateway 192.168.0.1
    dns-nameservers 8.8.8.8.8.8.4.4

allow-hotplug wlan
iface wlan0 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
    wpa-ssid "YourSSID"
    wpa-psk "YourPassword"

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


在这里,我注释掉了wpa conf的行,并添加了一行来配置无线接入点的SSID和密码。这是目前最简单的快速接入WiFi的方式。如果你希望在这个接口上使用静态IP,除了SSID和密码配置之外,还可以对eth0接口进行相同的更改。
WPA代表WiFi保护接入,WPA增加了更多的安全协议,使WiFi更安全,更难入侵。让我们首先将接口文件恢复为默认文件,以使用wpa_supplicant.conf文件:

source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

# iface eth0 inet manual
iface eth0 inet static
    address 192.168.0.100
    netmask 255.255.255.0
    gateway 192.168.0.1
    dns-nameservers 8.8.8.8.8.8.4.4

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


取消对wpa conf行的注释并删除wpa ssid和wpa psk行意味着wlan0接口现在将引用wpa_supplicant配置的conf文件。ssid和psk选项表示ssid名称和密码。scan_ssid=0行让系统知道这不是一个隐藏网络。如果是隐藏网络,则需要将值从0更改为1。key_mgmt=WPA-PSK行表示接入点正在使用的密码加密。WPA-PSK应适用于大多数家庭用户。如果在办公环境中工作,可能需要将其更改为其他内容。可以通过参考wpa_supplicant.conf的手册页来了解wpa_ supplicaant支持的所有加密类型。

ctrl-interface=DIR=/var/run/wpa_supplicant GROU{=netdev
update_config=1
country=GB

network={
    ssid="YourSSID"
    scan_ssid=0
    psk="YourPassword"
    key_mgmt=WPA-PSK
}
network={
    ssid="OtherSSID"
    scan_ssid=0
    psk="OtherPassword"
    key_mgmt=WPA-PSK
}


完成网络配置后,实现更改的最简单方法就是重新启动设备。

网络启动方面类命令:

①主机名的修改、启动与观察:

$ vim /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=www.centos.vbird

$ vim /etc/hosts


修改完毕后要顺利启动的话,得要重新启动设备才可以,因为系统已经有非常多的服务启动了,这些服务如果需要主机名,都是到这个档案去读取的。

$ hostname

$ ping -c 2 www.centos.vbird


②任意启动TCP/UDP封包的端口联机:nc, netcat。nc指令可以用来作为某些服务的检测,因为它可以连接到某个port来进行沟通,还可以自行启动一个port来倾听其他用户的联机。

# 激活一个port 20000来监听使用者的联机要求
$ nc -l localhost 20000 &
$ netstat -tlunp &; grep nc


③/etc/init.d/network restart这个script最重要,因为可以一口气重新启动整个网络的参数,它会主动的去读取所有的网络配置文件,所以可以很快的恢复系统默认的参数值。
④ifup eth0 (ifdown eth0) 启动或者是关闭某个网口。
⑤设定网络参数需修改/etc/sysconfig/network-scripts/ifcfg-eth0,ifcfg-eth0与档案内的DEVICE名称设定需相同,并且在这个档案内的所有设定,基本上就是bash的变量设定规则(注意大小写)!

$ vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0" # 网卡代号 必须要ifcfg -u相对应
HWADDR="08:00:27:71:85:BD" # 网卡地址 若只有一张网卡 可省略此项目
NM_CONTROLLED="no" # 不要受到其他软件的网络管理
ONBOOT="yes" # 是否默认启动此接口
BOOTPROTO=none # 取得IP的方式 其实关键词只有dhcp 手动可输入none
IPADDR=192.168.1.100 # 就是IP
NETMASK=255.255.255.0 # 就是子网掩码
GATEWAY=192.168.1.254 # 预设路由
# 重点是上面几个设定项目 底下的可以省略
NETWORK=192.168.1.0 # 就是该网段的第一个IP
BROADCAST=192.168.1.255 # 就是广播地址
MTU=1500 # 就是最大传输单元的设定值


<1>BOOTPROTO:启动该网络接口时使用何种协议?如果是手动给予IP的环境,请输入static或none,如果是自动取得IP时,请输入dhcp;
<2>GATEWAY:代表的是整个主机系统的default gateway,注意不要有重复设定的情况发生,也就是当你有ifcfg-eth0, ifcfgeth1…等多个档案,只要在其中一个档案设定GATEWAY即可。

$ /etc/init.d/network restart


⑥自动取得 IP 参数DHCP的设置方法:

$ vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR="08:00:27:71:85:BD"
NM_CONTROLLED="no"
ONBOOT=yes
BOOTPROTO=dhcp


只要上图几个项目即可,其他的都注释掉,尤其是那个GATEWAY一定不能设定,避免互相干扰!
⑦iwlist:利用无线网卡进行无线AP的侦测与取得相关的数据;
⑧iwconfig:设定无线网卡的相关参数;
⑨手动使用DHCP自动取得IP参数:dhclient

$ dhclient eth0


⑩ping,主要透过ICMP封包来进行整个网络的状况报告,最重要的就是ICMP type 0, 8这两个类型,分别是要求回报与主动回报网络状态是否存在的特性;另一个相当重要的是TTL属性:

# 侦测一下168.95.1.1 这部DNS主机是否存在
$ ping -c 3 168.95.1.1

网络状态监控类命令:

①netstat这个指令比较常被用在网络的监控方面:

<1>Proto:网络的封包协议,主要分为TCP与UDP封包;
<2>Recv-Q:非由用户程序链接到此socket复制的总bytes数;
<3>Send-Q:非由远程主机传送过来的acknowledged总bytes数;
<4>Local Address:本地端的IP:port情况
<5>Foreign Address:远程主机的IP:port情况
<6>State:联机状态,主要有建立ESTABLISED及监听LISTEN。
②如果想要检查目前主机启动在网络端口监听的服务有哪些,并且关闭不要的程序,可通过网络监听的端口分析,使用如下的方式分析:

$ netstat -tulnp


现在假设想要关闭avahi-daemon这个服务以移除该服务启动的端口时,应该利用/etc/init.d/xxx stop关闭,再使用chkconfig去处理开机不启动的行为。不过因为启动的服务名称与实际指令可能不一样,我们在netstat上看到的program项目是实际软件执行文件,可能与/etc/init.d/底下的服务档名不同,可能需要使用grep去获取数据,或者透过tab键去取得相关的服务档名才行。

$ /etc/init.d/avahi-daemon stop
$ chkconfig avahi-daemon off

③网络参数综合指令:ip,ip link可以设定与装置device有关的相关参数,包括MTU以及该网口的MAC等,当然也可以启动up或关闭down某个网络接口。

# 启动 关闭与设定装置的相关信息
$ ip link set eth0 up # 启动eth0这个转置接口
$ ip link set eth0 down 
$ ip link set eth0 mte 1000 # 更改MTU的值达到1000bytes

# 修改网卡代号、MAC等参数
$ ip link set eth0 name vbird
# 因为该装置目前是启动的 所以不能这样设定 应该这样做
$ ip link set eth0 down # 关闭界面
$ ip link set eth0 name vbird #重新设定
$ ip link show # 观察一下


设定前可能得要先关闭该网卡,否则会不成功。

④追踪测试整个网络传输的最大MTU:

需要知道的是,由于IP封包表头 (不含options) 就已经占用了20bytes,再加上ICMP的表头有8bytes,所以当你使用-s size时,那个封包的大小就得要先扣除(20+8=28)的大小。因此如果要使用MTU为1500时,就要下达ping –s 1472 -M do xx.yy.zz.ip才行。
⑤host:用来查出某个主机名的IP

⑥nslookup:用来作为IP与主机名对应的检查

⑦tcpdump:文字接口封包提取器。tcpdump是一个监听软件,甚至可以说是个黑客软件,因为它不但可以分析封包的流向,连封包的内容也可以进行监听,如果你使用的传输数据是明码的话,在router或hub上面就可能被人家监听走了

网络故障排查类命令:

①命令行下载工具wget命令
wget是一个Linux命令行下的文件下载工具。对于Linux运维人员来说是必备的工具。wget工具体积虽小,但功能完善,它支持断点下载功能,同时支持FTP、HTTP和HTTPS下载方式,支持代理服务器,使用起来也很方便。
<1>使用wget下载单个文件:

# wget https://mirrors.edge.kernel/pub/linux/kernel/v4.x/linux-4.20.17.tar.gz

<2>使用wget的-limit -rate参数进行限速下载(限速1MB/s下载):

# wget --limit-rate=1M http://mirrors.163/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD/1810.iso

<3>使用wget-c断点续传(wget的断点续传是自动的,只需要使用-c参数即可):

# wget -c http://mirrors.163/centos/7.6.1810/isos/x86_64/CentOS/x86_64-DVD-1810.iso

<4>测试服务器是否支持断点续传:
Web服务器(如Apache、Nginx)会默认开启对断点续传的支持。断点续传是在发起HTTP请求的时候加入Range头来告诉服务器客户端已经下载了多少字节。

# wget -S http://mirrors.163 2 > &1 | grep “Accept-Ranges”
# wget -S https://mirrors.aliyun/centos/timestamp.txt 2 > &1 | grep Ranges

输出结果中如果有Accept-Ranges: bytes,说明服务器支持按字节断点续传下载。
使用wget下载文件并以不同的文件名保存:

# wget -O php-7.3.2.tar.bz2 http://cn2.php/get/php-7.3.2.tar.bz2/from/this/mirror

②强大的HTTP命令行工具curl
curl命令是在命令行方式下工作,利用URL语法进行数据或者文件的传输。curl支持30多种类型的传输方式,其中最常使用的有FILE、FTP、HTTP、HTTPS等协议。
<1>通过curl显示网站的header信息(通过-I参数):

# curl -I https://www.ixdba

<2>显示网站的HTTP状态代码:
在对Web页面进行监控时,会经常通过状态码来判断网页状态,如果返回状态码非200,则认为网页异常。可使用-s,-o和-w的参数组合

# curl -s -o /dev/null -w %{http_code}”\n” http://www.baidu

其中,-s表示安静模式,不输出错误或者进度条之类的信息;-o表示指定输出结果到某个文件,不指定的话默认输出到终端,这里将结果写入空设备;-w表示输出一些定义的元数据。
通过HHTTP协议访问一个网站:

# curl -s -o /dev/null -w %{http_code}” ”%{time_total}” ”%{redirect_url}”\n” http://www.ixdba

<3>使用curl实现URL地址重定向:
默认情况下curl不会发送HTTP Location headers(重定向),但使用了-L选项后,当一个被请求页面移动到另一个站点时,就会发送一个HTTP Location header作为请求,然后将请求重定向到新的地址。

# curl -L -I http://www.ixdba

<4>抓取网页内容并保存到本地:

# curl -O https://www.ixdba/archives/2017/06/653.html
# curl -o test.html https://www.ixdba/archives/2017/06/653.html

其中-o用于将文件保存在命令行中指定文件名的文件中。
<5>通过curl下载文件并开启断点续传(其实比wget更好用):

# curl -C - -O http://mirrors.163/centos/7.6.1810/isos/x86_64/CentOS/x86_64-DVD-1810.iso

其中-C -表示自动断点续传,否则需要手动指定断点的字节位置。
<6>对curl的网络使用带宽进行限速:

# curl --limit-rate 2M -O http://mirrors.163/centos/7.6.1810/isos/x86_64/CentOS/x86_64-DVD-1810.iso

③Linux系统之间文件传输工具scp命令
scp就是secure copy,用于将文件或者目录从一个Linux系统复制到另一个Linux系统下。scp传输数据用的是SSH协议,保证了数据传输的安全性。
<1>scp复制本地文件到远程主机:

# scp /home/ixdba/etc.tar.gz root@192.168.60.168:/tmp
# scp root@192.168.60.133:/home/ixdba/etc.tar.gz /tmp

<2>scp复制本地目录到远程主机:

# scp -r /etc root@192.168.60.135:/opt

④动态路由追踪及网络故障排查工具mtr命令:
其相当于ping、traceroute、nslookup三个命令的集合,需要先安装。
⑤如果联机到yahoo网站的速度比平常慢,你觉得是<1>自己的网络环境有问题,<2>外部的Internet有问题?如果是<1>的话,当然需要检查自己的网络环境,看看是否有谁中毒了。但如果是Internet的问题,那只有等了!判断是<1>还是<2>就得使用traceroute这个指令:

# 侦测本机到yahoo去的各节点联机状态
$ traceroute -n tw.yahoo


这个指令会针对欲连接目的地的所有node进行UDP的逾时等待,例如上面的例子当中,由鸟哥的主机连接到Yahoo时,会经过12个节点以上,traceroute会主动的对这12个节点做UDP的回声等待并侦测回复的时间,每节点侦测三次,最终回传像上头显示的结果。可以发现每个节点其实回复的时间大约在50 ms以内,算是还可以的Internet环境。比较特殊的算是第10/12个,会回传星号,代表该node可能设有某些防护措施,让我们发送的封包信息被丢弃所致。因为我们是直接透过路由器转递封包,并没有进入路由器去取得路由器的使用资源,所以某些路由器仅支持封包转递,并不会接受来自客户端的各项侦测!此时就会出现上述问题。因为traceroute预设使用UDP封包,如果你想尝试使用其他封包,那么-I或-T可以试试看!由于目前UDP/ICMP的攻击层出不穷,因此很多路由器可能就此取消这两个封包的响应功能,所以我们可以使用TCP来侦测!例如使用同样的方法,透过等待时间1秒,以及TCP 80埠口的情况下,可以这样做:

$ traceroute -w 1 -n -T tw.yahoo

七、网络性能优化

网络内核参数优化在Linux作为Web服务器时,是必须要优化的一个环节。Linux上关于网络内核参数非常多,合理的内核参数设置,可以最大限度地发挥Web服务器的网络连接性能
①/proc/sys/net/ipv4/tcp_syn_retries,其表示对于一个新建连接,内核要发送多少个SYN连接请求才决定反求,建议设置为2;
②/proc/sys/net/ipv4/tcp_keepalive_time,其表示当keepalive启用的时候,TCP发送keepalive消息的频度,建议设置为300s;
③/proc/sys/net/ipv4/tcp_orphan_retires,其表示孤儿Socket废弃前重试的次数,重负载Web服务器建议调小;
④/proc/sys/net/ipv4/tcp_syncookie,其表示开启SYN Cookie。当出现SYN等待队列溢出时,启用Cookies来处理,可防范少量SYN攻击。默认值为0,表示关闭。针对SYN攻击,可以启用SYN Cookie、设置SYN队列最大长度以及设置SYN+ACK最大重试次数。设置tcp_syncookies为1就是启用了SYN Cookie。SYN Cookie的作用是缓解服务器资源压力。
⑤/proc/sys/net/ipv4/tcp_max_syn_backlog,其表示设置SYN队列最大长度,默认值为1024,加大队列长度为8192,可容纳更多等待连接的网络连接数。tcp_max_syn_backlog是使用服务器的内存资源换取更大的等待队列长度,让攻击数据包不至于占满所有连接而导致正常用户无法完成握手,所以会消耗系统部分内存资源。
⑥/proc/sys/net/ipv4/tcp_synack_retries,其用来降低服务器SYN+ACK报文重试次数(默认是5次),尽快释放等待资源。此参数是决定内核在放弃连接之前所送出的SYN+ACK的数目。
参数④、⑤、⑥的调整是双刃剑,设置过大可能消耗服务器更多的内存资源,甚至影响正常用户建立TCP连接,因此需要评估服务器硬件资源和攻击力度谨慎设置。
⑦/proc/sys/net/ipv4/tcp_tw_recycle,其表示开启TCP连接中TIME-WAIT sockets的快速回收,默认值为0表示关闭。通过开启TIME-WAIT sockets的快速回收,可以在很大程度上减轻高并发下的Web服务器负担,所以Web服务器中关于TIME-WAIT的优化是必须要做的。
⑧/proc/sys/net/ipv4/tcp_tw_reuse,其表示开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接,因为重用连接比重新建立新连接要方便得多。启用该resuse时必须同时启用快速回收recycle。
⑨/proc/sys/net/ipv4/tcp_fin_timeout,表示处于TIME-WAIT状态的连接在回收前必须等待的最小时间,改小它可以加快回收。
⑩/proc/sys/net/ipv4/tcp_keepalive_probes,表示用来减少超时前的探测次数。
⑪/proc/sys/net/core/netdev_max_backlog,其用来设置每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。修改此参数可以优化网络设备接收队列。
⑫/proc/sys/net/core/rmem_max、wmem_max,其可以提高TCP的最大缓冲区大小,即接收套接字、发送套接字缓冲区大小(以字节为单位);
⑬/proc/sys/net/ipv4/tcp_rmem、tcp_wmem,其可以提高Linux内核自动对Socket缓冲区进行优化的能力,即用来配置读缓冲、写缓冲的大小;
⑭/proc/sys/net/core/somaxconn,其用来设置Socket监听listen的backlog上限。backlog就是Socket的监听队列,当一个请求request尚未被处理或建立时,它会进入backlog。而Socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。当Server处理请求较慢,以至于监听队列被填满后,新来的请求会被拒绝。

除了网络通信外,服务器程序通常还必须考虑许多其他细节问题,这些细节问题涉及面广且零碎,而且基本上是模板式的,所以称之为服务器程序规范。例如
①Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程daemon。它没有控制终端,因而也不会意外接收到用户输入。守护进程的父进程通常是init进程(PID为1的进程)。
②Linux服务器程序通常有一套日志系统,它至少能输出日志到文件,有的高级服务器还能输出日志到专门的UDP服务器。大部分后台进程都在/var/log目录下拥有自己的日志目录。
③Linux服务器程序一般以某个专门的非root身份运行,例如mysqld、httpd、syslogd等后台进程,分别拥有自己的运行账户mysql、apache和syslog。
④Linux服务器程序通常是可配置的。服务器程序通常能处理很多命令行选项,如果一次运行的选项太多,则可以用配置文件来管理。绝大多数服务器程序都有配置文件,并存放在/etc目录下。
⑤Linux服务器进程通常会在启动的时候生成一个PID文件并存入/var/run目录中,以记录该后台进程的PID。例如syslogd的PID文件是/var/run/syslogd.pid。
⑥Linux服务器程序通常需要考虑系统资源和限制,以预测自身能承受多大负荷,例如进程可用文件描述符总数和内存总量等。

网络不通的可能硬件原因
①网线长度超过100m;
②网络设备旁有强磁波;
③一个BNC网段里最多只能接30台计算机,且网线总长不能超过185m,还需要添加信号放大装置。
网络不通的可能软件原因
①网卡的IP/netmask设定错误:例如同一个IP在同一个网段中出现造成IP冲突、子网掩码设定错误、网卡的驱动程序使用错误、网卡的IRQ、I/O Address的设定冲突等;
②路由的问题 (route table):最常见的就是预设路由 (default gateway) 设定错误!或者路由接口不符所导致的问题,使得数据封包没有办法顺利的送出去。
③通讯协议不相符:最常发生在不同的操作系统之间的通讯传输,例如早期Windows 98与Windows 2000之间的『网芳』若要达成沟通,则Windows 98必须要加装NetBEUI这个通讯协议才行。例如两部Linux主机要透过NFS通讯协议传输数据时,两边都得要支持rpcbind这个启动RPC协议的程序才行!
④网络负荷的问题 (loading): 当同时有大量的数据封包涌进Server或者是Hub或者是同一个网域中,就有可能造成网络的停顿甚至挂点!另外如果区网内有人使用BT (P2P软件) 或者是有人中毒导致蠕虫充满整个区网,也会造成网络的停顿问题;
⑤其他问题:例如一些port被防火墙挡住,造成无法执行某些网络资源;应用程序本身的Bug问题;应用程序中用户的网络设定错误;以及不同的操作系统的兼容性问题等。
处理时把握两个原则
①先由自身的环境侦测起,可以由自身PC上的网卡查起,到网络线、到Hub再到调制解调器等的硬件先检查完。在这个步骤中,最好用的软件就是ping,而你最好能有两部以上的主机来进行联机的测试;
②确定硬件没问题了,再来思考软件的设定问题!实际上如果网络不通时,你可以依序这样处理:
①了解问题:这个问题是刚刚发生?还是因为之前我做了什么动作而导致无法联机?例如之前鸟哥曾经更新过一个核心,结果该核心并不能驱动鸟哥的新网卡…
②确认IP:先看看自己的网卡有无驱动?能否取得正确的IP相关参数来联机?
③确认区网联机:利用ping来沟通两部主机 (路由器或IP分享器),确定网络线与中继的hub/switch工作正常;
④确认对外联机:看主机或IP分享器能否顺利取得IP参数,并以ping的方法确定对外联机是可以成功的 (例如 ping 168.95.1.1);
⑤确认DNS查询:利用nslookup或host或dig检查www.google看看;
⑥确认Internet节点:可以利用traceroute检查各节点是否没问题?
⑦确认对方服务器正常服务:是否对方服务器忙线中?或他的机器挂了?
⑧确认我方服务器:如果是别人连不上我这部主机,那检查主机某些服务正确启动否?可利用netstat检查。或是否某些安全机制的软件没有设定好,例如SELinux这项机制;
⑨防火墙或权限的问题:是否由于权限设定错误所致?是否由于你的机器有防火墙忘记启用可联机的端口所致?这个可以透过tcpdump来处理
步骤一:网卡工作确认
①确定网卡已经驱动成功;
②确定可以手动直接建立IP参数:

# ifconfig eth0 192.168.1.100
# ping 192.168.1.100

如果有响应的话,那表示这个网卡的设定应该是没有问题!
步骤二:局域网络内各项连接设备检测
关于Gateway与DNS的设定:Gateway与DNS最容易被搞混~应该填写IP分享器 (或NAT主机) 的IP在Gateway中,填写168.95.1.1在DNS的IP设定当中
关于Windows端的工作组与计算机名称:假如你需要资源共享,那么就必须在windows系统中开放档案分享,并且建议所有的计算机将工作组设定相同,但计算机名称不能相同!这个只与网络邻居及SAMBA服务器有关。
假设你的区网内所有的主机IP都设定正确了,那么接下来就可以使用ping来测试两部区网内主机的联机,这个联机的动作可以让你测试两部主机间的各项设备,包括网线、Hub/Switch等。
步骤三:取得正确的IP参数
在确认所有的区网没有问题之后,立即以ifconfig看看有没有捉到正确的IP?在台湾如果使用ADSL联机的话,应该可以顺利的取得一组正确的Public IP参数!
为了避免switch以及ADSL调制解调器热宕,鸟哥就买了桌上型小电扇,配合定时器 (timer) 来定时的向这两个设备吹风~为啥需要定时器?因为担心电风扇一直开着会烧掉…步骤四:确认路由表的规则
尝试使用ping来连连看Hinet的DNS主机也就是168.95.1.1那部机器!

# ping –c 3 168.95.1.1

如果有响应,就表示你的网络基本上已经没有问题,可以连到Internet了!如果你的public IP无法连接到外部 (例如168.95.1.1) ,可能问题就出在路由与防火墙上面了。假设你没有启动防火墙,那问题就缩小到剩下路由~路由的问题如何检查?就用route -n来检查!

仔细看上面的路由输出,第一条是ppp0产生的public IP接口,第二条是eth0的内部网域接口,再看到最后一条的0.0.0.0/0.0.0.0这个预设路由,竟然是内部网域的eth0为gateway。最大的问题应该是出在ifcfg-eth0里面不小心设定了GATEWAY=192.168.1.2所致,解决的方法为:
①取消ifcfg-eth0内GATEWAY=192.168.1.2那一行,(该行亦可能出现在 /etc/sysconfig/network 内)
②重新启动网络/etc/init.d/network restart
③重新进行拨接:adsl-stop; adsl-start
步骤五:主机名与IP查询的DNS错误
如果你发现可以ping到168.95.1.1这个Internet上面的主机,却无法使用浏览器在网址列浏览http://www.google的话,那肯定99%以上问题是来自DNS解析的困扰!解决的方法就是直接到 /etc/resolv.conf 去看看设定值对不对

$ vim /etc/resolv.conf

注意:Windows端的DNS设定与主机端/etc/resolv.conf的内容相同即可!很多初学者都以为TCP/IP内的DNS主机是填上自己的Linux主机,这是不对的 (除非你自己的Linux上面有DNS服务)!你只要填上你的ISP给你的DNS主机IP位置就可以了。
/etc/hosts与你的主机名对应,对于内部私有网域来说是相当重要的设定项目!
步骤六:Linux的NAT服务器或IP分享器出问题NAT主机一定是部路由器,所以你必须要在Linux上面观察好正确的路由信息。
步骤七:Internet的问题
想要确认是否问题来自Internet的话,就使用traceroute!查察看问题是来自那个地方再说!
步骤八:服务器的问题
服务器的问题包括有:
①服务器没有开放该项服务:例如主机关闭了telnet,那你使用telnet去联机,是无法连接上的!
②主机的权限设定错误:例如你将某个目录设定为drwx------,该目录拥有者为root,你却将该目录开放给WWW来浏览,由于WWW无法进入该目录,所以当然无法正确的给客户端浏览!这是最典型的权限设定错误的情况!
③安全机制设定错误:例如SELinux是用来更细微控管主机存取的一种核心机制,结果你启动的是系统原先不支持的类型,那么SELinux反而可能会抵挡该服务的提供!而其他例如/etc/hosts.deny, PAM模块等,都可能造成使用者无法登入的问题!这就不是网络问题,而是主机造成联机无法成功!
④防火墙问题:防火墙设定错误也是一个很常见的问题,你可以使用tcpdump来追踪封包的流向,以顺利的了解防火墙是否设定错误。

八、常见网络安全攻防

防火墙其实是一种网络数据的过滤方式,它可以依据你服务器启动的服务来设定是否放行,也能够针对你信任的用户来放行
Linux系统有内建的防火墙机制,因此你的联机能不能成功,得要先看防火墙的脸色才行。预设的Linux防火墙有两个机制,这两个机制都是独立存在的,因此我们预设就有两层防火墙。第一层是封包过滤式的netfilter防火墙,另一个则是透过软件控管的TCP Wrappers防火墙
①封包过滤防火墙:IP Filtering或Net Filter要进入Linux本机的封包都会先通过Linux核心的预设防火墙,就是netfilter。简单的说,就是iptables这个软件所提供的防火墙功能,因为它主要是分析TCP/IP的封包表头来进行过滤的机制,主要控制的就是MAC, IP, ICMP, TCP与UDP的端口与状态(SYN, ACK…)等。
②第二层防火墙:TCP Wrappers通过netfilter后,网络封包会开始接受Super daemons及TCP_Wrappers的检验,说穿了就是/etc/hosts.allow与/etc/hosts.deny的配置文件功能。这个功能是针对TCP的Header进行再次的分析,同样你可以设定一些机制来抵制某些IP或Port,好让来源端的封包被丢弃或通过检验。
Linux的防火墙功能之所以好,是因为它本身是由Linux内核所提供,由于直接经过内核来处理,因此效能非常好!

当一个网络封包要进入到主机之前,会先经由NetFilter进行检查,就是iptables规则。检查通过则接受ACCEPT进入本机取得资源,如果检查不通过,则可能予以丢弃DROP!上图中主要的目的是说明:规则是有顺序的!例如当网络封包进入Rule 1的比对时,如果比对结果符合Rule 1,此时这个网络封包就会进行Action 1的动作,而不会理会后续的Rule 2, Rule 3…等规则。而如果这个封包并不符合Rule 1的比对,那就会进入Rule 2的比对!如此一个一个规则去进行比对就是了。如果所有的规则都不符合,此时就会透过预设动作(封包政策Policy)来决定这个封包的去向。所以当你的规则顺序排列错误时,就会产生很严重的错误了。假设你的Linux主机提供了WWW服务,自然就要针对port 80来启用通过的封包规则,但你发现IP来源为192.168.100.100老是恶意的尝试入侵你的系统,所以你想要将该IP拒绝往来,所有的非WWW封包都给他丢弃。就这三个规则来说,应如下设定防火墙检验顺序:
<1> Rule 1先抵挡192.168.100.100;
<2> Rule 2再让要求WWW服务的封包通过;
<3> Rule 3将所有的封包丢弃。
这样的排列顺序就能符合你的需求,不过万一你的顺序排错了变成:
<1> Rule 1先让要求WWW服务的封包通过;
<2> Rule 2再抵挡192.168.100.100;
<3> Rule 3将所有的封包丢弃。
预设情况下Linux的iptables至少有三个表格,包括管理本机进出的filter、管理后端主机(防火墙内部的其他计算机)的nat、管理特殊旗标使用的mangle (较少使用)。还可以自定义额外的链!每个表格与其中链的用途分别是:
①filter过滤器:主要跟进入Linux本机的封包有关,这个是预设的table!
<1>INPUT:主要与想要进入我们Linux本机的封包有关;
<2>OUTPUT:主要与我们Linux本机所要送出的封包有关;
<3>FORWARD:与Linux本机比较没有关系,它可以转递封包到后端的计算机中,与下列nat table相关性较高。
②nat地址转换:是Network Address Translation的缩写,这个表格主要在进行来源与目的之IP或port的转换,与Linux本机无关,主要与Linux主机后的局域网络内计算机较有相关。
<1>PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
<2>POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
<3>OUTPUT:与发送出去的封包有关
③mangle破坏者:这个表格主要是与特殊的封包的路由标志有关,早期仅有PREROUTING及OUTPUT链,从kernel 2.4.18后加入了INPUT及FORWARD链。由于这个表格与特殊标志相关性较高,所以像咱们这种单纯的环境当中,较少使用mangle这个表格。
所以如果你的Linux是作为WWW服务,那么要开放客户端对你的WWW要求有响应,就得要处理filter的INPUT链;而如果你的Linux是作为局域网络的路由器,那么就得要分析nat的各个链以及filter的FORWARD链才行。也就是说,其实各个表格的链结之间是有关系的!由于mangle表格很少被使用,将其拿掉后简单的关系如下图:

因为网络是双向的,所以进与出要分开来看!因此进入的封包需要路由判断,送出的封包当然也要进行路由判断才能够发送出去!nat表格的使用需要很清晰的路由概念才能够设定好,建议新手先不要碰,最多就是先玩一玩最阳春的nat功能“路由器功能”就好!
理论上,当你安装好Linux之后,系统应该会主动帮你启动一个阳春的防火墙规则,不过这个防火墙可能不是我们想要的模式,因此需要额外进行一些修订的行为。防火墙的设定主要使用的就是iptables这个指令。而防火墙是系统管理员的主要任务之一,且对于系统的影响相当的大,因此只能让root使用iptables,不论是设定还是观察防火墙规则。

# 列出filter table三条链的规则
$ iptables -L -n
# 列出nat table三条链的规则
$ iptables -t nat -L -a


在上表中每一个Chain就是前面提到的每个链。Chain那一行里面括号的policy就是预设的政策
<1>target:代表进行的动作,ACCEPT是放行,而REJECT则是拒绝,此外尚有DROP丢弃的项目!
<2>prot:代表使用的封包协议,主要有tcp, udp及icmp三种封包格式;
<3>opt:额外的选项说明;
<4>source:代表此规则是针对哪个来源IP进行限制;
<5>destination:代表此规则是针对哪个目标IP进行限制。
在输出结果中,第一个范例因为没有加上-t的选项,所以默认就是filter这个表格内的INPUT, OUTPUT, FORWARD三条链的规则。若针对单机来说,INPUT与FORWARD算是比较重要的管制防火墙链,所以你可以发现最后一条规则的政策是REJECT拒绝!虽然INPUT与FORWARD的政策是放行ACCEPT,不过在最后一条规则就已经将全部的封包都拒绝了。
我们将INPUT的5条规则依据输出结果来说明一下,结果会变成:
<1>只要是封包状态为RELATED,ESTABLISHED就予以接受
<2>只要封包协议是icmp类型的,就予以放行
<3>无论任何来源(0.0.0.0/0)且要去任何目标的封包,不论任何封包格式 (prot为all),通通都接受
<4>只要是传给port 22的主动式联机tcp封包就接受
<5>全部的封包信息通通拒绝鸟哥建议使用iptables-save这个指令来观察防火墙规则,因为iptables-save会列出完整的防火墙规则,只是并没有规格化输出而已。

$ iptables -save [-t table]
$ iptables -save


如何清除规则:

$ iptables [-t tables] [-FXZ]
$ iptables -F
$ iptables -X
$ iptables -Z


一般来说,我们在重新定义防火墙的时候都会先将规则给清除掉,然后一条一条来设定会比较容易一点。当你的封包不在你设定的规则之内时,则该封包的通过与否,是以Policy的设定为准,在本机方面的预设政策中,假设你对于内部的使用者有信心的话,那么filter内的INPUT链方面可以定义的比较严格一点,而FORWARD与OUTPUT则可以制订的松一些!通常鸟哥都是将INPUT的policy定义为DROP,其他两个则定义为ACCEPT。至于nat table则暂时先不理会。

$ iptables [-t nat] -P [INPUT,OUTPUT,FORWARD] [ACCEPT,DROP]
$ iptables -P INPUT DROP
$ iptables -P OUTPUT ACCEPT
$ iptables -P FORWARD ACCEPT
$ iptables -save


如果站在客户端且不提供网络服务的Linux本机角色时,应该要有的规则如下
①规则归零:清除所有已经存在的规则 (iptables -F…)
②预设政策:除了INPUT这个自定义链设为DROP外,其他为预设ACCEPT;
③信任本机:由于lo对本机来说是相当重要的,因此lo必须设定为信任装置;
④回应封包:让本机主动向外要求而响应的封包可以进入本机(ESTABLISHED,RELATED)
⑤信任用户:这是非必要的,如果你想要让区网的来源可用你的主机资源时。

$ vim bin/firewall.sh
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin; export PATH

# 1. 清除规则
iptables -F
iptables -X
iptables -Z
# 2. 设定政策
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
# 3-5. 制订各项规则
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -m state --state RELATED, ESTABLISHED -] ACCEPT
#iptables -A INPUT -i eth0 -s 192.168.1.0/24 -] ACCEPT
# 6. 写入防火墙规则到配置文件
/etc.init.d/iptables save

$ sh bin/firewall.sh


①/proc/sys/net/ipv4/tcp_syncookies:启用核心的SYN Cookie模块,其可以在系统用来启动随机联机的端口(1024:65535)即将用完时自动启动。透过此一机制可以大大的降低无效的SYN等待端口,而避免SYN Flooding的DoS攻击!

$ echo "1"; /proc/sys/net/ipv4/tcp_syncookies


但是这个设定值由于违反TCP的三向交握(因为主机在发送SYN/ACK之前需要先等待client的序号响应),所以可能会造成某些服务的延迟现象,例如SMTP (mail server)。不过总的来说这个设定值还是不错的,只是不适合用在负载已经很高的服务器内!因为负载太高的主机有时会让内核误判为遭受SYN Flooding攻击。
②/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts:想象一下,如果有个搞破坏的人使用1000台主机传送ping给你的主机,而且每个ping都高达数百Kbytes时,你的网络带宽要么就是带宽被吃光,要么可能系统会宕机,这种方式分别被称为ping flooding (不断发ping) 及ping of death (发送大的ping封包)。可通过取消ICMP类型8的ICMP封包回应来避免。我们可以透过防火墙来抵挡,这也是比较建议的方式。内核取消ping回应的设定值有两个,分别是:/proc/sys/net/ipv4内的icmp_echo_ignore_broadcasts (仅有ping broadcast地址时才取消ping的回应) 及icmp_echo_ignore_all (全部的ping都不回应)。鸟哥建议设定icmp_echo_ignore_broadcasts就好,可以这么做:

$ echo "1"; /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts


③/proc/sys/net/ipv4/conf/网络接口/*:内核还可以针对不同的网络接口进行不一样的参数设定,网络接口的相关设定放置在/proc/sys/net/ipv4/conf/当中。

单机防火墙示例

鸟哥偏好使用脚本来撰写防火墙,然后透过最终的/etc/init.d/iptables save来将结果储存到/etc/sysconfig/iptables去!此特色还可以用在呼叫其他的scripts,可以让防火墙规则具有较为灵活的使用方式
示例防火墙可用来作为路由器上的防火墙,也可以用来作为本机的防火墙。假设硬件联机如下图所示,Linux主机本身也是内部LAN的路由器,即是一个简单的路由器的功能!
①外部网络使用eth0 (如果是拨接,有可能是ppp0);
②内部网络使用eth1,且内部使用192.168.100.0/24这个Class
③主机默认开放的服务有WWW, SSH, https等。

由于希望将信任网域LAN与不信任网域Internet整个分开的完整一点,所以希望你可以在Linux上面安装两块以上的实体网卡,将两块网卡接在不同的网域,这样可以避免很多问题。至于最重要的防火墙政策是:关闭所有的联机,仅开放特定的服务模式。而且假设内部使用者已经受过良好的训练,因此在filter table的三条链个预设政策是:
①INPUT为DROP
②OUTPUT及FORWARD为ACCEPT
鸟哥预计提供的防火墙流程是这样的:

为了未来修改维护的方便,鸟哥将整个script拆成三部分,分别是:
①iptables.rule:设定最基本的规则,包括清除防火墙规则、加载模块、设定服务可接受等;
②iptables.deny:设定抵挡某些恶意主机的进入;
③iptables.allow:设定允许某些自定义的后门来源主机!
鸟哥个人习惯是将这个脚本放置到/usr/local/virus/iptables目录下,你也可以自行放置到自己习惯的位置去。
在这里插入图片描述

$ mkdir -p /usr/local/virus/iptables
$ cd /usr/local/virus/iptables
$ vim iptables.rule
# 请先输入你的相关参数
EXTIF="eth0" # 这个是可以连上Public IP的网络接口
INIF="eth1" # 内部LAN的连接接口 若无则写成INIF=""
INNET="192.168.100.0/24" # 若无内部网域接口 则写成INNET=""
export EXTIF INIF INNET
# 第一部分 针对本机的防火墙设定
# 1. 先设定好核心的网络功能
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
for i in /proc/sys/net/ipv4/conf/*/{rp_filter, log_martians}; do
    echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/{accept_source_route, accept_redirects,\
send_redirects}; do
    echo "0" > $i
done
# 清除规则 设定默认政策及开放 lo 与相关的设定值
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin; export PATH
iptables -F
iptables -X
iptables -Z
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# 3. 启动额外的防火墙前script模块
if [-f /usr/local/virus/iptables/iptables.deny]; then
    sh /usr/local/virus/iptables/iptables.deny
fi
if [-f /usr/local/virus/iptables/iptables.allow]; then
    sh /usr/local/virus/iptables/iptables.allow
fi
if [-f /usr/local/virus/httpd-err/iptables.http]; then
    sh /usr/local/virus/httpd-err/iptables.http
fi
# 4. 允许某些类型的ICMP封包进入
AICMP="0 3 3/4 4 11 12 14 16 18"
for tyicmp in $AICMP
do
    iptables -A INPUT -i $EXTIF -p icmp --icmp-type $tyicmp -j ACCEPT
done
# 5. 允许某些服务的进入 请依照你自己的环境启动
# iptables -A INPUT -p TCP -i $EXTIF --dport 21 --sport 1024:65534 -j ACCEPT #FTP
# iptables -A INPUT -p TCP -i $EXTIF --dport 22 --sport 1024:65534 -j ACCEPT #SSH
# iptables -A INPUT -p TCP -i $EXTIF --dport 25 --sport 1024:65534 -j ACCEPT #SMTP
# iptables -A INPUT -p TCP -i $EXTIF --dport 53 --sport 1024:65534 -j ACCEPT #DNS
# iptables -A INPUT -p TCP -i $EXTIF --dport 53 --sport 1024:65534 -j ACCEPT #DNS
# iptables -A INPUT -p TCP -i $EXTIF --dport 80 --sport 1024:65534 -j ACCEPT #WWW
# iptables -A INPUT -p TCP -i $EXTIF --dport 110 --sport 1024:65534 -j ACCEPT #POP3
# iptables -A INPUT -p TCP -i $EXTIF --dport 443 --sport 1024:65534 -j ACCEPT #HTTPS

# 第二部分 针对后端主机的防火墙设定
# 1. 先加载一些有用的模块
modules="ip_tables iptable_nat ip_nat_ftp ip_nat_irc ip_conntrack ip_conntrack_ftp ip_conntrack_irc"
for mod in $modules
do
    testmod=`lsmod | grep "^${mod} " | awk '{print $1}'`
    if ["$testmod" == ""]; then
        modprobe $mod
    fi
done
# 2. 清除NAT table的规则
iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
# 3. 若有内部接口的存在(双网卡)开放成为路由器 且为IP分享器
if ["$INIF" != ""]; then
    iptables -A INPUT -i $INIF -j ACCEPT
    echo "1" | /proc/sys/net/ipv4/ip_forward
    if ["$INNET" != ""]; then
        for innet in $INNET
        do
            iptables -t nat -A POSTROUTING -s $innet -o $EXTIF -j MASQUERADE
        done
    fi
fi
# 如果你的MSN一直无法联机 或者是某些网站OK 某些网站不OK
# 可能是MTU的问题 那你可以将底下这一行给他取消批注来启动MTU限制范围
# iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu

# 4. NAT服务器后端的LAN内对外的服务器设定
# iptables -t nat -A PREROUTING -p tcp -i $EXTIF --dport 80 \
#          -j DNAT --to-destination 192.168.1.210:80 # www

# 5. 特殊的功能 包括windows远程桌面所产生的规则 假设桌面主机为1 2 3 4
# iptables -t nat -A PREROUTING -p tcp -s 1.2.3.4 --dport 6000 \
#          -j DNAT --to-destination 192.168.100.10
# iptables -t nat -A PREROUTING -p tcp -s 1.2.3.4 --sport 3389 \
#          -j DNAT --to-destination 192.168.100.20

# 6. 最终将这些功能储存下来
/etc/init.d/iptables save 

基本上只要修改一下最上方的接口部分就能够运作这个防火墙了。不过因为每个人的环境都不相同,因此在设定完成后,依旧需要测试一下才行!
关于iptables.allow的内容,假如要让一个140.116.44.0/24这个网域的所有主机来源可以进入自己主机的话,则这个档案的内容可以写成这样:

将这三个档案的权限设定为700且只属于root权限后,就能够直接执行iptables.rule!不过要注意的是,在上面的案例中鸟哥预设将所有的服务通道都是关闭的,所以必须要到本机防火墙的第5步处将一些注释#解开才行。如果有其他更多的port想要开启时,一样需要增加额外的规则才行。如果希望一开机就自动执行script的话,可将这个档案的完整档名写入/etc/rc.d/rc.local当中:

预设的防火墙是Linux的内建功能,但防火墙主要管理的是MAC, IP, Port等封包表头方面的信息,如果想要管控某些目录进入,某些目录无法使用的功能,就得要透过权限以及服务器软件提供的相关功能。例如,你可以在httpd.conf这个配置文件内规范某些IP来源不能使用httpd这个服务来取得主机的数据,那么即使该IP通过前面两层的过滤,它依旧无法取得主机的资源!但要注意的是,如果httpd这支程序本来就有问题的话,那么client端将可直接利用httpd软件的漏洞来入侵主机,而不需要取得主机内root的密码!因此,要小心这些启动在因特网上面的软件。
为了避免前一个步骤的权限误用,或者是程序有问题所造成的资安状况,安全强化SELinux来发挥它的功能。简单的说,SELinux可以针对网络服务的权限来设定一些规则policy,让程序能够进行的功能有限,因此即使使用者的档案权限设定错误,以及程序有问题时,该程序能够进行的动作还是被限制的,即使该程序使用的是root权限也一样。例如,前一个步骤的httpd真的被黑客攻击而让对方取得root的使用权,由于httpd已经被SELinux控制在/var/www/html里面,且能够进行的功能已经被规范住了,因此黑客就无法使用该程序来进行系统的进一步破坏。
想一想你使用浏览器连接到WWW主机最主要的目的是什么,当然是读取主机的WWW数据!所以最终网络封包其实是要向主机要求文件系统的数据。这里假设你要使用httpd这支程序来取得系统的档案数据,但httpd默认是由一个系统账号名称为httpd来启动的,所以你的网页数据权限当然就是要让httpd这支程序可以读取才行。如果你前面三关的设定都OK,最终权限设定错误,使用者依旧无法浏览你的网页数据的。
在这些步骤之外,Linux以及相关软件都可能还会支持登录文件记录功能,记录历史历程以方便管理者在未来的错误查询与入侵检测,良好的分析登录档的习惯是一定要建立的,尤其是/var/log/messages与/var/log/secure这些档案
防火墙规则通常需要设定的地方有
①服务:一般来说,如果你的Linux server是作为Internet的服务器,提供的是比较一般的服务,那么只要处理“服务”项目即可。这里假设你的服务器已经提供了ssh与dhcpv6-client的服务端口。
②端口:如果你提供的服务所启用的端口并不是正规端口,例如,为了玩systemd与SELinux,曾经将ssh端口调整到222,同时也曾经将ftp的端口调整到555。那如果你想要让其他人连进来,就不能只开放上面的“服务”项目,连这个“端口”的地方也需要调整才行。另外,如果有某些比较特别的服务是系统预设没有提供的,“服务”当然也就不存在了,这时你可以直接透过端口来搞定。
③丰富规则(rich rule):如果你有整个网域需要放行或者是拒绝的时候,那么前两个项目就没有办法适用,这时就得要这个项目来处理。
④界面:就是这个网域主要是针对哪一个网卡来做规范的意思,一般只有一张网卡,所以当然就是eth0!

程序员所撰写的程序并非十全十美,所以总是可能有些地方没有设计好,因此就造成所谓的程序漏洞。程序漏洞所造成的问题有大有小,小问题可能是造成主机的宕机,大问题则可能造成主机的机密数据外流,或者主机的操控权被黑客取得。在现今网络发达的年代,程序的漏洞问题是造成主机被攻击、入侵的最主要因素之一。因此,快速有效的针对程序漏洞进行修补,是一个很重要的维护课题

封包过滤式的网络防火墙可以抵挡掉一些可能有问题的封包,Linux系统上面挡掉封包的机制很简单:既然封包的表头上面已经有这么多的重要信息,那么我就利用一些防火墙机制与软件来进行封包表头的分析,并且设定分析的规则,当发现某些特定的IP、特定的端口或者是特定的封包信息(SYN/ACK等),就将该封包丢弃,这就是最基本的防火墙原理。例如大家都知道telnet这个服务器挺危险的,而telnet使用的port number为23,所以当使用软件去分析要送进我们主机的封包时,只要发现该封包的目的地是我们主机的port 23,就将该封包丢掉。
如果以OSI七层协议来说,每一层可以抵挡的数据有:
第二层:可以针对来源与目标的MAC进行抵挡;
第三层:主要针对来源与目标的IP,以及ICMP的类别type进行抵挡;
第四层:针对TCP/UDP的端口进行抵挡,也可以针对TCP的状态code来处理。

很多团体做过许多操作系统安全性侦测的研究,它们发现一部没有经过更新与保护的Linux/Windows主机(不论是一般个人计算机还是服务器),只要一接上Internet几乎可以在数小时内就被入侵或被当成跳板!要好好的保护好自己的服务器主机才行。基本上,你最要知道的是你的服务器开了多少网络服务,而这些服务会启动什么端口。根据这层关系来关闭一些不必要的网络服务,再利用在线更新系统让你的Linux随时保持在最新的软件的状态,这个小动作可以预防绝大部分的入侵攻击,可以说是最重要的一步,最后才是架设基础防火墙。

SELinux是Security Enhanced Linux的缩写,即安全强化的Linux之意,其是整合进Linux内核的一个在进行进程、文件等细部权限设定依据的模块。其最初是为了防止由于权限设置不当,导致内部员工系统资源误用,所产生的系统问题。由于启动网络服务的也是进程,因此刚好也能控制网络服务能否存取系统资源,所以也具有网络安全强化的功能。
系统仅依据进程拥有者与文件资源的rwx权限来决定有无对文件存取的能力,这种存取文件系统的方式称为自主式访问控制DAC。其存在以下严重缺点:
①root具有最高权限:如果不小心某支进程被别人取得,且该进程属于root权限,则这支进程就可以在系统上进行任何资源的存取;
②使用者可以取得进程来变更文件资源的访问权限:如果不小心将某个目录的权限设定为777,由于对任何人的权限都会变成rwx,于是该目录就会被任何人任意存取。
SELinux为了避免DAC容易发生的问题,其导入了委任式访问控制MAC方法。其可以针对特定的进程与特定的文件资源来进行权限管控,这样即使你是root,在使用不同的进程时,所能获取的权限也不一定是root,而要看当时该进程的设定而定。如此一来针对控制的主体就变成进程,而不再是使用者!此外这个主体进程也不能任意使用系统文件资源,因为每个文件资源也有针对该主体进程设定可取用的权限,这样控制程度就细化很多。但整个系统进程和文件都非常多,一项一项控制是不可能人工实现的,所以SELinux提供一些预设的策略policy,并在策略内提供多个规则rule,让人可以选择是否启用某个控制规则。
在委任式访问控制的设定下,我们进程能够活动的空间就变小了。例如WWW服务器软件的达成进程为httpd程序,默认情况下httpd仅能在/var/www/目录底下存取文件。如果httpd进程想要到其他目录去存取数据时,除了规则设定要开放外,目标目录也得要设定成httpd可读取的模式type才行。由于限制非常多,所以即使不小心httpd被黑客取得了控制权,他也无权浏览/etc/shadow等重要的配置文件。

上左图是没有SELinux的DAC存取结果,apache这支root主导的进程可以在3个目录内做任何文件的新建与修改。上右图是加上SELinux的MAC管理的结果,SELinux仅会针对apache这支进程放行部分目录。
SELinux的相关重要定义:
①主体subject:SELinux主要想要管理的就是进程,因此可以将主体与进程划等号;
②目标object:主体进程能否存取的目标资源一般就是文件系统,因此可以将目标与文件系统划等号;
③策略policy:由于进程与文件数量庞大,SELinux会依据某些服务来制订基本的存取安全性策略,这些策略内还会有详细的规则rule来指定不同的服务开放某些资源的存取与否。目前仅提供3个主要策略:
<1>targeted:针对网络服务限制较多,针对本机限制较少,是预设的策略;
<2>minimum:由targeted修订而来,仅针对选择的进程来保护;
<3>mls:完整的SELinux限制,限制方面较为严格。
建议使用预设的targeted策略即可。
④安全性文本security context:主体能否存取目标除了策略之外,主体与目标的安全性文本必须一致才能够顺利存取。这个安全性文本security context优点类似文件系统的rwx,如果设定错误,你的某些服务(主体进程)就无法存取文件系统(目标资源),也就会一直出现权限不符的错误信息。


如上图所示:主体进程必须要通过SELinux政策内的规则放行后,就可以与目标资源进行安全性文本的比对;若比对失败则无法存取目标,若比对成功则可以开始存取目标。如此一来加入SELinux之后,如果出现权限不符的情况时,就得要一步一步的分析可能的原因。
可通过命令ls -Z查看安全性文本:(注意:必须已经启动了SELinux才行,若没有启动,ls -Z不起作用。)

$ ls -Z


安全性文本主要用:分为三个字段,各字段的意义为:
Identify: role: type
身份识别:角色:类型
①身份识别Identify:相当于账号方面的身份识别,主要的身份识别常见有以下几种常见类型:
<1>unconfined_u:不受限用户,也就是说该文件来自于不受限的进程所产生的。一般来说我们使用可登入账号来取得bash之后,预设的bash环境是不受SELinux管制的,因为bash并不是什么特别的网络服务。因此在这个不受SELinux所限制的bash进程所产生的文件,其身份识别大多就是unconfined_u;
<2>system_u:系统用户,大部分就是系统自己产生的文件。
基本上如果是系统或软件本身所提供的文件,大多都是system_u这个身份名称;而如果是用户通过bash自己建立的文件,大多都是不受限的unconfined_u身份;而如果是网络服务所产生的文件或者系统服务运行过程产生的文件,大多都是system_u身份。
②角色Role:通过角色字段我们可以知道这个资料是属于进程、文件资源还是代表使用者。一般的角色有:
<1>object_r:代表的是文件或目录等文件资源,其是最常见的;
<2>system_r:代表的是进程,一般使用者也会被指定为system_r。
③类型Type(最重要):在预设的targeted政策中,Identify与Role字段基本上是不重要的,重要的在于这个类型字段。基本上一个主体进程能不能读取到这个文件资源与类型字段有关。而类型字段在文件与进程的定义不太相同,分别是:
<1>type:在文件资源Object上面称为类型type;
<2>domain:在主体进程Subject则称为领域domain。
如果domain与type搭配,该进程才能够顺利的读取文件资源。
通过身份识别与角色字段的定义,我们可以约略知道某个进程所代表的意义:

$ ps -eZ


这些对应资料在targeted策略下的对应如下:

在预设的target策略下其实最重要的字段是类型字段,主体与目标之间是否具有可以读写的权限与进程的domain及文件的type有关。这里以crond以及其配置文件,即/usr/sbin/crond,/etc/crontab,/etc/cron.d等来说明:

$ ps -eZ | grep cron
# 再来瞧执行档 配置文件等的安全文本内容为何
$ ll -Zd /usr/sbin/crond /etc/crontab /etc/cron.d


当我们执行/usr/sbin/crond之后,这个程序的进程的domain类型是crond_t,而这个crond_t能够读取的配置文件则为system_cron_spool_t这种类型,因此不论/etc/crontab,/etc/cron.d以及/var/spool/cron都会是相关的SELinux类型(/var/spool/cron为user_cron_spool_t)。

上图表示的意义为:
①首先我们触发一个可执行的目标文件,就是具有crond_exec_t这个类型的/usr/sbin/crond文件;
②该文件的类型会让这个文件所造成的主体进程具有crond这个领域domain,该策略针对这个领域已经制定了许多规则,其中包括这个领域可以读取的目标资源类型;
③由于crond domain被设定为可以读取system_cron_spool_t这个类型的目标文件,因此你的配置文件放到/etc/cron.d/目录下,就能够被crond进程读取了;
④但最终能不能读到正确的资料,还得看rwx是否符合Linux权限的规范。
上述流程的重点有:
①策略内需要制订详细的domain/type相关性;
②若文件的type设定错误,即使权限设定为rwx全开的777,该主体进程也无法读取目标文件资源。

# 先假设你因为不熟的缘故 因此在root家目录 建立一个cron设定
$ vim checktime
10 * * * * root sleep 60s

# 检查后才发现文件放错目录了 又不想要保留副本 因此使用mv移动到正确目录
$ mv checktime /etc/cron.d
$ ll /etc/cron.d/checktime

# 强制重新启动crond 然后偷看一下登录档 看看有没有问题发生
$ systemctl restart crond
$ tail /var/log/cron



目前SELinux依据启动与否共有3种模式
①强制模式enforcing:代表SELinux运行中,且已经正确的开始限制domain/type了;
②宽容模式permissive:代表SELinux运行中,不过仅会有警告信息并不会实际限制domain/type的存取。这种模式可以用于SELinux的debug;
③关闭disabled:SELinux并没有实际运作。

如上图所示,并不是所有的进程都会被SELinux所管制,因此最左边会出现一个所谓的“有受限的进程主体”。可通过命令ps -eZ查看进程有没有受限confined:

$ ps -eZ | grep -E 'cron|bash'


可通过命令getenforce来查看当前的SELinux模式:

$ getenforce


可通过命令sestatus来查看SELinux的策略:

$ sestatus [-vb]
$ sestatus



SELinux的配置文件是/etc/selinux/config,若需要修改预设策略的话,直接修改配置文件内容为
SELINUX=enforcing
即可。
如果修改了SELinux的策略或启动模式就需要重新启动SELinux,这是因为SELinux是整合到内核里面的,你只可以在SELinux运行下切换为enforcing或permissive模式,不能直接关闭SELinux。但如果启动SELinux,由于系统必须要针对文件写入安全性文本的信息,因此开机过程会花费不少时间在等待重新写入SELinux安全性文本。

$ setenforce [0|1]
# 将SELinux在Enforcing与permissive之间切换与观察
$ setenforce 0
$ getenforce
$ setenforce 1
$ getenforce



某些特殊情况下,SELinux从Disabled切换成Enforcing模式后,会有一堆服务无法顺利启动,会报错“/lib/xxx里面的数据没有权限读取,所以启动失败”。最简单的处理方法是先切换到Permissive模式,然后使用命令 restorecon -Rv / 重新还原所有SELinux类型,再切换到Enforcing模式就可以了。
可通过命令sestatus -b或getsebool -a来查询系统上的全部规则是否启动:

$ getsebool [-a] [规则的名称]
# 查询本系统内所有的布尔值设定状况
$ getsebool -a


可通过命令chcon手动修改文件的SELinux type,正确的SELinux type应该以/etc/cron.d/底下额定文件为标准来处理。而使用命令restorecon主动恢复预设的SELinux type要简单的多,且可以一次恢复整个目录下的文件,因此实际中基本不使用chcon命令。可通过命令restorecon让文件恢复正确的SELinux type:

$ restorecon [-Rv] 文件或目录
# 将/etc/cron.d/底下的文件通通恢复成预设的SELinux type
$ restorecon -Rv /etc/cron.d
$ systemctl restart crond
$ tail /var/log/cron


可通过命令semanage增删改查预设的SELinux type:

# 查询一下 /etc /etc/cron.d的预设SELinux type
$ semanage fcontext -l | grep -E '^/etc |^/etc/cron'


假设我们要建立一个/srv/mycron目录,该目录默认需要设置为system_cron_spool_t类型:

# 1. 先建立/srv/mycron同时在内部放入配置文件 同时观察SELinux type
$ mkdir /srv/mycron
$ cp /etc/cron.d/checktime /srv/mycron
$ ll -dZ /srv/mycron /srv/mycron/checktime
# 2. 观察上层/srv的SELinux type
$ semanage fcontext -l | grep '^/srv'
# 3. 将mycron默认值改为system_cron_spool_t
$ semanage fcontext -a -t system_cron_spool_t "/srv/mycron(/.*)?"
$ semanage fcontext -l | grep '^/srv/mycron'
# 4. 恢复/srv/mycron以及子目录相关的SELinux type
$ restorecon -Rv /srv/mycron
$ ll -dZ /srv/mycron /srv/mycron/*



Linux系统提供了auditd和setroubleshootd服务来侦测在登录SELinux时产生的错误。几乎所有SELinux相关的程序都以se开头,setroubleshootd服务会将关于SELinux的错误信息与解决方法记录到/var/log/messages与/var/log/setroubleshoot/*里。其需要安装setroublshoot和setroubleshoot-server两个软件。但在最新的Linux系统中将auditd和setroubleshootd服务的记录整合到auditd当中。
Linux提供几支侦测的服务在登录SELinux产生的错误,就是auditd与setroubleshootd
①setroubleshoot --> 错误讯息写入/var/log/messages。原本的SELinux信息是以两个服务来记录的,分别是auditd与setroubleshootd。既然是同样的信息,因此Linux将两者整合在auditd当中,所以并没有setroubleshootd的服务存在了!因此当安装好setroubleshoot-server后,请记得要重新启动auditd,否则setroubleshootd的功能不会被启动。事实上Linux对setroubleshootd的运作方式是:
<1>先由auditd去呼叫audispd服务,
<2>然后audispd服务去启动sedispatch程序,
<3>sedispatch再将原本的auditd讯息转成setroubleshootd的讯息,进一步储存下来!

$ apt install setroubleshoot setroubleshoot-server
$ /etc/init.d/auditd restart

$ cat /var/log/messages | grep setroubleshoot


常见的攻击手法与相关保护
①取得帐户信息后猜密码:如果你常常观察你的主机登录文件,那会发现如果你的主机有启动Mail server服务时,你的登录档就会常常出现有些黑客尝试以一些奇怪的常见账号在试图猜测你的密码,例如admin, administrator, webmaster …之类的账号,尝试来窃取你的私人信件。如果你的主机真的有这类账号,而且这类账号还没有良好的密码规划,那就容易中标!不过这种攻击方式比较费时,因为目前很多软件都有密码输入次数的限制,如果连续输入三次密码还不能成功的登入,那该次联机就会被断线。所以这种攻击方式日益减少。
基本的应对措施有
<1>减少信息的曝光机会:例如不要将Email Address随意散布到Internet上;
<2>建立较严格的密码设定规则:包括/etc/shadow, /etc/login.defs等档案的设定;
<3>完善的权限设定:由于这类的攻击方式会取得你的某个使用者账号的登入权限,所以如果你的系统权限设定得宜的话,那么攻击者也仅能取得一般使用者的权限而已,对于主机的伤害比较有限!
②利用系统的程序漏洞主动攻击:如果你的主机有开放网络服务时,就必须有启动某个网络软件!我们也知道由于软件可能撰写方式的问题,可能产生一些会被黑客乱用的蠕虫程序代码。这种攻击模式是目前最常见的,因为攻击者只要拿到攻击程序就可以进行攻击,而且由攻击开始到取得你系统的root权限不需要猜密码,不到两分钟,就能够立刻入侵成功。但如果你的主机随时保持在实时更新的阶段,或者关闭大部分不需要的程序,那就可以躲避过这个问题。
基本的应对措施有
<1>关闭不需要的网络服务:开的port越少,可以被入侵的管道越少,一部主机负责的服务越单纯,越容易找出问题点。
<2>随时保持更新;
<3>关闭不需要的软件功能:例如远程登录服务器SSH可以提供root由远程登录,那么危险的事情当然要取消!
③利用社交工程作欺骗:就是透过人与人的互动(就是电信诈骗)来达到入侵的目的!
基本的应对措施有
<1>追踪对谈者:不要一味的相信对方,你必须要有信心的向上呈报,不要一时心慌就中计!
<2>不要随意透露账号/密码等信息:最好不要随意在Internet上面填写这些数据。
④利用程序功能的被动攻击:如果你喜欢上网随意浏览的话,那么有的时候可能会连上一些广告很多,或者是一堆弹出式窗口的网站。如果你常常注意一些网络危机处理的相关新闻时,常会发现Windows的浏览器有问题,有时则是全部的浏览器(Firefox, Netscap, IE…)都会出现问题。这是因为很多浏览器会主动的应答对方WWW主机所提供的各项程序功能,或者是自动安装来自对方主机的软件,有时浏览器还可能由于程序发生安全问题,让对方WWW浏览器传送恶意代码给你的主机来执行。
基本的应对措施有
<1>随时更新主机上的所有软件;
<2>较小化软件的功能:例如让你的收信软件不要主动的下载文件,让你的浏览器在安装某些软件时,要通过你的确认后才安装,这样就比较容易克服一些小麻烦;
<3>不要连接到不明的主机:不要以为没有连接上恶意网站就不会有问题!
⑤蠕虫或木马的rootkit:rootkit意思是说可以取得root权限的一群工具组kit,就如同前面主动攻击程序漏洞的方法一样,rootkit主要也是透过主机的程序漏洞。不过rootkit也会透过社交工程让用户下载安装,结果让黑客绑架对方主机!rootkit除了可以透过上述方法来进行入侵之外,还会伪装或者是进行自我复制,例如很多的rootkit本身就是蠕虫或者是木马间谍程序。蠕虫会让你的主机一直发送封包向外攻击,结果会让你的网络带宽被吃光。至于木马程序(Trojan Horse)则会对你的主机进行开启后门(开一个port来让黑客主动入侵),结果就是绑架!rootkit其实挺不好追踪的,因为很多时候他会主动的去修改系统观察的指令,包括ls, top, netstat, ps, who, w, last, find等,让你看不到某些有问题的程序,如此一来你的Linux主机就很容易被当成是跳板了!
基本的应对措施有
<1>不要随意安装不明来源的档案或者是不明网站的档案数据;
<2>不要让系统有太多危险的指令:例如SUID/SGID的程序,这些程序很可能会造成用户不当的使用,而使得木马程序有机可趁!
<3>可以定时以rkhunter之类的软件(杀毒软件)来追查。
⑥DDoS攻击法 (Distributed Denial of Service ):中文翻译成分布式阻断服务攻击,它就是透过分散在各地的僵尸计算机进行攻击,让你的系统所提供的服务被阻断而无法顺利的提供服务给其他用户的方式。这种攻击法也很要命,而且方法很多,最常见的就属SYN Flood攻击法!当主机接收了一个带有SYN的TCP封包之后,就会启用对方要求的port来等待联机,并且发送出回应封包(带有SYN/ACK标记的目标TCP封包),并等待Client端的再次回应。如果client端在发送出SYN封包后,却将来自Server端的确认封包丢弃,那你的Server端就会一直空等,而且Client端可以透过软件功能,在短短的时间内持续发送出这样的SYN封包,那么你的Server就会持续不断的传送确认封包,并且开启大量port空等。等到主机的全部port都启用完毕,系统就挂了!更可怕的是,通常攻击主机的一方不会只有一部!它会透过Internet上面的僵尸网络(已经成为跳板,但网站主却没有发现的主机)发动全体攻击,让你的主机在短时间内就立刻挂点。最常被用来作为阻断式服务的网络服务就是WWW,因为WWW通常得对整个Internet开放服务。这种攻击方法是最难处理的。
⑦其他:例如IP欺骗,它可以欺骗你主机告知该封包来源是来自信任网域,而且透过封包传送的机制,由攻击的一方持续的主动发送出确认封包与工作指令。如此一来你的主机可能就会误判该封包确实有响应,而且是来自内部的主机。不过我们知道因特网是有路由的,而每部主机在每一个时段的ACK确认码都不相同,所以这个方式要达成可以登入会比较麻烦,所以不太容易发生在小型主机上面!
基本的应对措施有
<1>设定规则完善的防火墙:利用Linux内建的防火墙软件iptables建立较为完善的防火墙,可以防范部分的攻击行为;
<2>核心功能:你必须要对系统核心有很深入的了解,才有办法设定好你的核心网络功能;
<3>登录文件与系统监控:你可以透过分析登录文件来了解系统的状况,也可以透过类似MRTG之类的监控软件来实时了解到系统是否有异常。
汇总起来的防护措施包括
<1>建立完善的登入密码规则限制;
<2>完善的主机权限设定;
<3>设定自动升级与修补软件漏洞、及移除危险软件;
<4>在每项系统服务的设定当中,强化安全设定的项目;
<5>利用iptables, TCP_Wrappers强化网络防火墙;
<6>利用主机监控软件如MRTG与logwatch来分析主机状况与登录文件。

如何避免用户乱用系统乱设定权限?这个时候就得要透过SELinux来控制了。SELinux可以在程序与档案之间再加入一道细部的权限控制,因此即使程序与档案的权限符合操作动作,但如果程序与档案的SELinux类型type不吻合时,那么该程序就无法读取该档案。此外,Linux也针对某些常用的网络服务制订了许多的档案使用规则rule,如果这些规则没有启用,那么即使权限、SELinux类型都对了,该网络服务的功能还是无法顺利的运作!

只有root才能启动的保留的port:在小于1024的端口,都是需要以root的身份才能启动的,这些port主要是用于一些常见的通讯服务,在Linux系统下常见的协议与port的对应是记录在/etc/services里面的。客户端启动程序时,随机启动一个大于1024以上的端口:客户端启动的port是随机产生的,主要是开启大于1024以上的端口。这个port也是由某些软件所产生的,例如浏览器、Filezilla这个FTP客户端程序等。所谓的监听是某个服务程序会一直常驻在内存当中,所以该程序启动的port就会一直存在。只要服务器软件激活的端口不同,就不会造成冲突。当客户端连接到此服务器时,透过不同的端口,就可以取得不同的服务数据。所以一部主机上面当然可以同时启动很多不同的服务!
事实上没有所谓的port安全性!因为port的启用是由服务软件所造成的,也就是说真正影响网络安全的并不是port,而是启动port的那个软件!对安全真正有危害的是某些不安全的服务,而不是开了哪些port!因此没有必要的服务就将其关闭,尤其某些网络服务还会启动一些port,尤其是高危port,例如22、8080、8000等!

在一般正常的Linux系统环境下,服务的启动与管理主要有两种方式:①Stand alone,就是直接执行该服务的执行档,让该执行文件直接加载到内存当中运作,用这种方式来启动可以让该服务具有较快速响应的优点。一般来说这种服务的启动script都会放置到/etc/init.d/这个目录底下,所以通常可以使用/etc/init.d/sshd restart之类的方式来重新启动这种服务;
②Super daemon用一个超级服务作为总管来统一管理某些特殊的服务。在Linux里面使用的则是xinetd这个。这种方式启动的网络服务虽然在响应上速度会比较慢,不过可以透过super daemon额外提供一些控管,例如控制何时启动、何时可以进行联机、哪个IP可以连进来、是否允许同时联机等。通常个别服务的配置文件放置在/etc/xinetd.d/当中,但设定完毕后需要重新以/etc/init.d/xinetd restart重新启动才行!
例如,如果想要将系统上面的port 111关掉的话,最简单的作法就是先找出那个port 111的启动程序:

$ netstat -tnlp | grep 111
$ which rpcbind
$ rpm -qf /sbin/rpcbind
$ rpm -qc rpcbind | grep init


假如我们知道系统的telnet服务通常是以super daemon来管控的,要启动telnet的步骤为:
①要启动telnet首先必须要已经安装了telnet的服务器才行,可以先以apt查询看看是否有安装telnet-server。如果没有安装的话,使用apt install telnet-server先安装;
②由于是super daemon管控,所以请编辑/etc/xinetd.d/telnet这个档案,将其中的disable = yes改成disable = no之后,以/etc/init.d/xinetd restart重新启动super daemon!③利用netstat -tnlp察看是否有启动port 111。
更进一步,只要端口不是用于网络服务都可以保留,如果是网络服务,建议不知道的服务就先关闭,以后用到相关服务时,再一个一个打开即可。鸟哥目前启动的网络服务有底下这些:

$ netstat -tlunp


其实一部主机最常发生问题的状况,都是由内部的网络误用所产生的,所以只管好主机是没有办法杜绝问题的!还需要做到:
①了解什么是需要保护的内容:如果你的主机相当的重要,请不要让任何人靠近!
②预防黑客的入侵:在预防这方面的攻击时,除了严格管制网络的登入之外,还需要特别控制原本你主机中的用户!就小网站来说,不要以为好朋友就随便!他说要指定密码是跟他的账号相同比较好记你就答应他!等到人家用他的密码登入你的主机,并破坏你的主机,那可就得不偿失!如果是大企业的话,员工使用网络时要分等级的!
③主机环境安全化:除了多关心还是多关心!仔细的分析登录档,常常上网看看最新的安全通告,这都是最基础的,还包含以最快的速度更新有问题的软件!
④防火墙规则的制定:这部份比较麻烦一些,因为你必需不断的测试测试再测试,以取得优化的网络安全设定!如果你的防火墙规则订定得太多时,一个数据封包就要经过越多的关卡才能完整的通过防火墙以进入到主机内部!这可是相当花费时间的,会造成主机的效能不彰!
⑤实时维护你的主机:防火墙不是一经设定之后就不用再管了,因为再严密的防火墙也会有漏洞的!这些漏洞包括防火规则设定不良、利用较新的侦测入侵技术、利用旧软件的服务漏洞等!所以必需要实时维护你的主机!包括分析log files,藉由PortSentry软件实时侦测!
⑥良好的教育训练课程:这也是公司需要网管的主因之一!
⑦完善的备份计划:一个良好的网站管理人员无时无刻都会进行重要数据的备份!可依靠rsync工具。

一部被入侵的主机如何修复的步骤
①立即拔除网络线:拿掉网络功能最简单的作法就是拔掉网线!拿掉网线最主要的功能除了保护自己之外,还可以保护同网域的其他主机。
②分析登录文件信息,搜寻可能的入侵途径:为什么我的主机这一次会被入侵,对方是如何入侵的?如果你能够找出问题点,那么不但你的Linux功力立刻增强了,主机也会越来越安全!
<1>分析登录档:低级的黑客通常仅是利用工具软件来入侵你的系统,所以我们可以藉由分析一些主要的登录档来找出对方的IP以及可能有问题的漏洞。可以分析/var/log/messages, /var/log/secure还有利用last指令来找出上次登入者的信息。
<2>检查主机开放的服务:找出你系统上面的服务,并且检查一下每个服务是否有漏洞,或者是在设定上面有了缺失,然后一个一个的整理。
<3>查询Internet上面的安全通报:透过安全通报来了解一下最新的漏洞信息,说不定你的问题就在上面!③重要数据备份:如果主机上面没有重要的数据,那么直接重新安装就好了。被入侵之后检查完了入侵途径,再来就是要备份重要的数据了。重要的数据应该是非Linux系统上面原有的数据,例如/etc/passwd, /etc/shadow, WWW网页的数据, /home里面的使用者重要档案等,至于/etc/*, /usr/, /var等目录下的数据就不需要备份了。注意:不要备份一些binary执行文件,因为Linux系统安装完毕后本来就有这些档案,此外这些档案也很有可能已经被窜改过了!
④重新全新安装:在这次安装中,你最好选择适合你自己的安装软件即可,不要全部软件都安装上去!
⑤软件的漏洞修补:重新安装完毕之后,请立即更新你的系统软件,否则还是会被入侵的!鸟哥喜欢先在其他比较干净的环境下将Internet上面的漏洞修补软件下载下来,然后刻录起来,然后拿到自己的刚刚安装完成的系统上面,mount CD之后全部给他更新,更新之后并且设定了相关的防火墙机制,进行下一步骤关闭或移除不需要的服务后,才将网线插上主机的网卡上!
⑥关闭或移除不需要的服务:⑦数据回复与恢复服务设定:刚刚备份的数据要赶紧的复制回系统,同时将系统的服务再次重新开放,请注意这些服务的设定最好能够再次的确认一下,避免一些不恰当的设定参数在里头!
⑧连上Internet:将刚刚拿掉的网线接上,恢复主机的运作!

维护网络服务器最简单的方式不是跑去实体服务器前面登入,而是透过远程联机服务器联机功能来登入主机,然后再进行其他有的没的维护就是Linux主机几乎都会提供sshd这个联机服务,而且这个服务还是主动进行数据加密的,这样信息在网络上面跑就安全多了
所谓的明码就是:当我们的数据封包在网络上传输时,该数据封包的内容为数据的原始格式,也就是说当你使用telnet登入远程主机时,要输入账号密码,那你的账号密码就是以原本的数据格式传输。所以如果被类似tcpdump之类的监听软件提取数据,那你的帐号密码就有可能被窃取!因此目前我们通常都希望使用可以将这些在网络上面跑的数据加密的技术,以增加数据在Internet上面传送的安全性。
数据加密,简单的说就是将人们看的懂得原始电子数据经过一些运算,让这些数据变成没有意义的乱码(至少对人类来说),然后再将其在网络上面传输。而当用户想要查阅这个数据时,再透过解密运算,将这些反推出原始的电子数据。由于这些数据已经被重新处理过,所以即使数据在因特网上被黑客监听而窃取,他们也不容易推算得出原始资料的内容。
SSH是Secure SHell protocol的简写 (安全的壳程序协议),它可以透过数据封包加密技术,将等待传输的封包加密后再传输到网络上。这个SSH协议在预设的状态中,本身就提供两个服务器功能:
①一个是类似telnet的远程联机使用shell的服务器,亦即是俗称的ssh;
②另一个就是类似FTP服务的sftp-server,提供更安全的FTP服务。
说SSH比较安全,其实是透过SSH信道传输信息时,该信息在网络上比较安全,因为数据是加密过的,即使被窃取对方可能也不会知道数据内容为何,因此信息比较安全。但这不代表SSH这个通讯协议就比较安全,两者意义不同!
SSH服务器端与客户端的联机步骤:
①服务器建立公钥档:每一次启动sshd服务时,该服务会主动去找/etc/ssh/ssh_host的档案,若系统刚刚安装完成时,由于没有这些公钥档案,因此sshd会主动去计算出这些需要的公钥档案,同时也会计算出服务器自己需要的私钥档;
②客户端主动联机要求:若客户端想要联机到ssh服务器,则需要使用适当的客户端程序来联机,包括ssh, pietty等客户端程序;
③服务器传送公钥档给客户端:接收到客户端的要求后,服务器便将第一个步骤取得的公钥档案传送给客户端使用 (此时应是明码传送,公钥就是给大家使用的!);
④客户端记录/比对服务器的公钥数据及随机计算自己的公私钥:若客户端第一次连接到此服务器,则会将服务器的公钥数据记录到客户端的用户家目录内的~/.ssh/known_hosts。若是已经记录过该服务器的公钥数据,则客户端会去比对此次接收到的与之前的记录是否有差异。若接受此公钥数据,则开始计算客户端自己的公私钥数据;
⑤回传客户端的公钥数据到服务器端:用户将自己的公钥传送给服务器。此时服务器:具有服务器的私钥与客户端的公钥,而客户端则是:具有服务器的公钥以及客户端自己的私钥,你会看到在此次联机的服务器与客户端的密钥系统(公钥+私钥)并不一样,所以才称为非对称式密钥系统;
⑥开始双向加解密:
<1>服务器到客户端:服务器传送数据时,拿用户的公钥加密后送出。客户端接收后,用自己的私钥解密;
<2>客户端到服务器:客户端传送数据时,拿服务器的公钥加密后送出。服务器接收后,用服务器的私钥解密。
客户端的密钥是随机运算产生于本次联机当中的,所以你这次的联机与下次的联机的密钥可能就会不一样!此外在客户端的用户家目录下的~/.ssh/known_hosts会记录曾经联机过的主机的public key,用以确认我们是连接上正确的那部服务器。由于服务器提供的公钥与自己的私钥都放置于/etc/ssh/ssh_host
,可以如下操作来得到公钥和私钥:

$ rm /etc/ssh/ssh_host*
$ /etc/init.d/sshd restart
$ date; 11 /etc/ssh/ssh_host*


在我们使用的Linux系统中,默认已经含有SSH的所有需要的软件了!这包含了可以产生密码等协议的OpenSSL软件与OpenSSH软件,所以要启动SSH直接启动就是了!在目前的Linux Distributions当中,都是预设启动SSH的,所以不用去设定!直接启动就是以SSH daemon,简称为sshd来启动的,所以手动可以这样启动:

$ /etc/init.d/sshd restart
$ netstat -tlnp | grep ssh


注意,SSH不但提供了shell给我们使用,亦即是ssh protocol的主要目的,同时亦提供了一个较为安全的FTP server,亦即是ssh-ftp server给我们当成FTP来使用!所以这个sshd可以同时提供shell与ftp,而且都是架构在port 22上面!
ssh:直接登入远程主机的指令。SSH在client端使用的是ssh这个指令,这个指令可以指定联机的版本(version1, version2),还可以指定非正规的ssh port (正规ssh port为22)。一般的用法可以使用如下方式:

# 1. 直接联机登入到对方主机的方法
$ ssh 127.0.0.1


一般使用ssh登入远程主机,都会填写“ssh账号@主机IP”的格式,意思是说使用该主机的某账号登入的意思。但很多人都不喜欢写账号,即使用“ssh主机IP”的格式。如果不写账号的话,会以本地计算机的账号来尝试登入远程。也就是说如果近端与远程具有相同的账号,那么不写账号也没有关系,如上表所示。

# 2. 使用student账号登入本机
$ ssh student@127.0.0.1
$ exit

# 3. 登入对方主机执行过指令后立刻离开的方式
$ ssh student@127.0.0.1 find ~/find1.log

# 4. 与上题相同 但让往对方主机自己跑该指示
$ ssh -f student@127.0.0.1 find ~/find1.log


如果想要让远程主机进行关机的指令,如果不加上-f参数,那你会等待对方主机关机完毕再将你踢出联机,这比较不合理。因此加上-f就会指定远程主机自己跑关机,而不需要再空空等待。例如:ssh –f root@some_IP shutdown -h now之类的指令。

# 5. 删除掉know_hosts后 重新使用root联机到本机 且自动加上公钥记录
$ rm ~/.ssh/known_hosts
$ ssh -o StrictHostKeyChecking=no root@localhost


服务器公钥记录文件:~/.ssh/known_hosts。当你登入远程服务器时,本机会主动的用接收到的服务器public key去比对~/.ssh/known_hosts有无相关的公钥,然后进行底下的动作:
①若接收的公钥尚未记录,则询问用户是否记录。若要记录 (范例中回答yes的那个步骤)则写入~/.ssh/known_hosts且继续登入的后续工作;若不记录 (回答no) 则不写入该档案,并且离开登入工作;
②若接收到的公钥已有记录,则比对记录是否相同,若相同则继续登入动作;若不相同则出现警告信息,且离开登入的动作。这是客户端的自我保护功能,避免你的服务器是被别人伪装的。
虽然说服务器的ssh通常可能会改变,如果是测试用主机,则常常在重新安装,那么服务器的公钥肯定经常不同,如此你就无法继续登入!可删除原有的系统公钥,重新启动ssh让你的公钥更新:

$ rm /etc/ssh/ssh_host*
/etc/init.d/sshd restart

然后重新使用底下的方式来进行联机动作:

$ ssh root@localhost


上述表格出现的错误讯息中,特殊字体的地方在告诉你:/root/.ssh/knownhosts 的第1行里面的公钥与这次接收到的结果不同,很可能被攻击了!使用vim到/root/.ssh/known_hosts,并将第1行(冒号 : 后面接的数字就是了) 删除,之后再重新ssh,系统又会重新问你要不要加上公钥!
Windows用户的SSH客户端联机程序
预设的Windows并没有ssh的客户端程序,因此所有的程序都得要下载其他第三方软件才行。常见的软件主要有pietty和putty。pietty官方网站:http://www.csie.ntu.edu.tw/~piaip/pietty/,在putty官方网站上有很多的软件可以使用,包括putty/pscp/psftp等,它们分别对应ssh/scp/sftp这三个指令。鸟哥爱用的pietty是putty的改版。pietty除了完整兼容putty之外,还提供选单与较为完整的文字编码。

在上图中箭头为1的地方填写相关的主机名或者IP,箭头2务必选择SSH那一项,至于箭头3的地方,鸟哥比较喜欢选单出现样式,因为可以直接修改一些pietty的环境设定值!若没有问题,按下联机后,就会出现如下等待登入与输入账/密数据的画面:

这个图标会让你以为是在主机前面工作,而且上头还有选单可以随时调整类似字形、字体、字符编码等重要环境参数。要解决画面当中会有乱码而不是正常的中文显示的问题,必须要牢记下面三个跟语系编码有关的数据要相同才行:
①文本文件本身在存档时所挑选的语系;
②Linux程序 (如bash软件) 本身所使用的语系 (可用LANG变量调整);
③pietty所使用的语系。
可以透过下图选单列当中的选项来处理,如下所示:

在选项的字符编码里面,可以挑选big5 (cp950)或者是unicode (utf8)的中文编码,让它符合你的Linux与档案所储存的数据格式,则中文字就OK了!如果想要作更细致的设定时,可以选择上图最底下的详细设定项目,就会出现下图。其中更为重要的是“键盘右侧的数字键想要生效”时,可以按照下图的指示来启动数字键的功能:

将上图中箭头2所指的那个项目勾选起来且按下Apply之后,你键盘右侧的数字键才能够
正常使用,否则按右侧数字键会乱码。你还可以调整pietty滚动条的记忆行数,这样当数据太多时,依旧可以调整滚动条来查阅之前的数据。设定方法如下:

这里我们可以调整为2那个项目,这样每次登入都会以version 2的模式登入主机了!

目前pietty已经支持中文,不过需要修改一下字符集,如下图设置:

将字型设定为细明体、字集设定为Big5,如此一来pietty就支持中文输入了!
上面我们作的这些设定值都记录在Windows的登录文件当中!你可以在Windows系统中,开始–>执行后,出现的框框内输入regedit,在左边的画面当中选择HKEYCURRENT_USER–> Software --> SimonTatham --> PuTTY --> Sessions,就可以看到你的设定值!
使用sftp-server的功能:psftp,其重点在使用sftp-server。使用的方式可以直接点选psftp这个档案让它直接启动,则会出现下面的图样:

这个时候可以填入你要连接上去的主机名,例如我的区域内网络192.168.100.254这部主机:

图形化接口的sftp客户端软件:Filezilla。Filezilla是图形接口的一个FTP客户端软件,使用上非常的方便。
sshd服务器细部设定:所有的sshd服务器详细设定都放在/etc/ssh/sshd_config里面。

$ vim /etc/ssh/sshd_config






Linux预设的sshd服务已经算是挺安全的,不过还不够!建议你
①将root的登入权限取消;
②将ssh版本设定为2;
③其他的设定值就依照自己的喜好来设定,通常不建议进行随便修改!
如果修改过上面这个档案(/etc/ssh/sshd_config),那就必需要重新启动一次sshd这个daemon才行!即:# /etc/init.d/sshd restart
制作不用密码可立即登入的ssh用户:我们可以将Client产生的Key给他拷贝到Server当中,以后Client登入Server时,由于两者在SSH要联机的信息传递中,就已经比对过Key了,因此可以立即进入数据传输接口中而不需要再输入密码!在实作上的步骤为:
①客户端建立两把钥匙:在密钥系统中,私钥比较重要,因此私钥才是解密的关键。所以这两把钥匙得在发起联机的客户端建置才对。利用指令ssh-keygen;
②客户端放置好私钥档案:将Private Key放在Client上面的家目录,即$HOME/.ssh/,并且得要注意权限!
③将公钥放置服务器端的正确目录与文件名:将Public Key放在任何一个你想要用来登入的服务器端的某User的家目录内之,.ssh/里面的认证档案即可完成整个程序。
①客户端建立两把钥匙:在clientlinux.centos.vbird这部主机上面以vbirdtsai的身份来建立两把钥匙即可。需要注意的是,我们有多种密码算法,如果不指定特殊的算法,则默认以RSA算法来处理:

$ ssh-keygen [-t rsa | dsa]
$ ssh-keygen
$ ls -ld ~/.ssh; ls -l ~/.ssh


注意,示例的身份是vbirdtsai,所以当执行ssh-keygen时,才会在家目录底下的.ssh/这个目录里面产生所需要的两把Keys,分别是私钥(id_rsa)与公钥(id_rsa.pub)。~/.ssh/目录必须要是700的权限才行!另外一个要特别注意的就是id_rsa的档案权限,它必须是-rw-------且属于vbirdtsai才行,否则在未来密钥比对的过程中,可能会被判定为危险而无法成功的以公私钥成对档案的机制来达成联机。
②将公钥档案数据上传到服务器上:因为我们要登入www.centos.vbird是以dmtsai的身份,因此我们就得要将上个步骤建立的公钥(id_rsa.pub)上传到服务器上的dmtsai用户才行。最简单的方法就是使用scp!

③将公钥放置服务器端的正确目录与文件名:我们必须要到服务器端的dmtsai这个用户身份下,将刚刚上传的id_rsa.pub数据附加到authorized_keys这个档案内才行。

# 1. 建立~/.ssh档案 注意权限需要为700
$ ls -ld .ssh
$ mkdir .ssh; chmod 700 .ssh
$ ls -ld .ssh

# 2. 将公钥档案内的数据使用cat转存到authorized_keys内
$ ls -l *pub
$ cat od_rsa.pub >> .ssh/authorized_keys
$ ls -l .ssh


这样就搞定密钥系统!以后你从clientlinux.centos.vbird的vbirdtsai登入到www.centos.vbird的dmtsai用户时,就不需要任何的密码!例如:在clientlinux的vbirdtsai身份中,将系统的/etc/hosts*档案复制给www.centos.vbird的dmtsai用户的家目录:

$ scp /etc/hosts* dmtsai@192.168.100.254:~
$ ssh dmtsai@192.168.100.254 "ls -l"


在建立密钥系统的步骤中要记得
①Client必须制作出Public & Private这两把keys,且Private需放到~/.ssh/内;
②Server必须要有Public Key,且放置到用户家目录下的~/.ssh/authorized_keys,同时目录的权限(.ssh/)必须是700而档案权限则必须为644,同时档案的拥有者与群组都必须与该账号吻合才行。
未来当你还想要登入其他的主机时,只要将你的public key (就是id_rsa.pub这个档案) 给拷贝到其他主机上面去,并且新增到某账号的~/.ssh/authorized_keys这个档案中即可!

其实大家都被“SSH是个安全的服务”所欺骗了,其实sshd并不怎么安全!翻开openssh的历史来看,确实有很多人是利用ssh的程序漏洞来取得远程主机的root权限,进一步黑掉对方的主机!所以,非必要不要将sshd对Internet开放可登入权限,尽量局限在几个小范围内的IP或主机名即可!关于安全设定方面,我们可以建议几个项目,分别由底下这三方面来进行
①服务器软件本身的设定强化:/etc/ssh/sshd_config
②TCP wrapper的使用:/etc/hosts.allow, /etc/hosts.deny
③iptables的使用:iptables.rule, iptables.allow
④服务器软件本身的设定强化:/etc/ssh/sshd_config
一般而言这个档案的默认项目就已经很完备了,事实上是不太需要更动它的!但如果你有些使用者方面的顾虑,可以这样修正一些问题:
①禁止root账号使用sshd的服务;
②禁止nossh群组的用户使用sshd的服务;
③禁止testssh用户使用sshd的服务。

# 1. 先观察一下所需要的账号是否存在
$ for user in sshnot1 sshnot2 sshnot3 testssh student; do \
> id $user | cut -d ' ' -f1-3; done

# 2. 修改sshd_config 并且重新启动sshd
$ vim /etc/ssh/sshd_config
$ /etc/init.d/sshd restart

# 3. 测试与观察相关的账号登入情况
$ ssh root@localhost 
$ tail /var/log/secure
$ ssh sshnot1@localhost
$ tail /var/log/secure


如果你的sshd只想让本机以及网域内的主机来源能够登入的话,那就这样做:

$ vim /etc/hosts.allow
$ vim /etc/hosts.deny


多几层保护也很好,可以在iptables.rule内将port 22的放行功能取消,然后再到iptables.allow里面新增这行:

$ vim /usr/local/virus/iptables/iptables.allow
$ /usr/local/virus/iptables/iptables.rule

九、主要服务器搭建

Linux最强大的功能就是网络功能!其实际就是一套非常稳定的操作系统,任何工作只要能在Linux这个操作系统上面跑,那它就是Linux可以达成的功能之一!所以Linux的作用主要在于网络服务器的架设。对于架设服务器来说,架站容易维护难,维护还好、排错更难!架设一个服务器只要一下午就可以完成,但这样一个网站,多则三天少则数小时,立刻就会被入侵!所以其维护会花费更多的精力。
虽然不同的服务器提供的服务并不相同,而且每种服务的原理也不见得都一样,不过每种服务器由规划、架设到后续的安全维护,其实整个流程是大同小异的

NAT的全名是Network Address Translation,意思是网络地址的转换。TCP/IP的网络封包不是有IP地址吗?IP地址不是有来源与目的吗?我们的iptables指令能够修改IP封包的表头数据,连目标或来源的IP地址都可以修改!甚至连TCP封包表头的port number也能修改!NAT服务器的功能可以达到类似IP分享的功能之外,还可以达到类似DMZ (非军事区) 的功能!这完全取决于我们的NAT是修改:来源IP还是目标IP!
若内部LAN有任何一部主机想要传送封包出去时,他是这样的:
①先经过NAT table的PREROUTING链;
②经由路由判断确定这个封包是要进入本机与否,若不进入本机则下一步;
③再经过Filter table的FORWARD链;
④通过NAT table的POSTROUTING链,最后传送出去。
NAT服务器的重点在于上面流程的第①和④步骤,也就是NAT table的两条重要的链:PREROUTING与POSTROUTING。这两条链有什么重要的功能呢?重点在于修改IP!但是这两条链修改的IP是不一样的!POSTROUTING在修改来源IP,PREROUTING则在修改目标IP。由于修改的IP不一样,所以就称为来源NAT (Source NAT, SNAT) 及目标NAT (Destination NAT, DNAT)。

如上图所示,在客户端192.168.1.100这部主机要联机到http://tw.yahoo去时,他的封包表头会如何变化?
①客户端所发出的封包表头中,来源会是192.168.1.100,然后传送到NAT这部主机;
②NAT这部主机的内部接口 (192.168.1.2) 接收到这个封包后,会主动分析表头数据,因为表头数据显示目的并非Linux本机,所以开始经过路由,将此封包转到可以连接到Internet的Public IP处;
③由于private IP与public IP不能互通,所以Linux主机透过iptables的NAT table内的Postrouting链将封包表头的来源伪装成为Linux的Public IP,并且将两个不同来源 (192.168.1.100及public IP) 的封包对应写入暂存内存当中,然后将此封包传送出去;此时Internet上面看到这个封包时,都只会知道这个封包来自那个Public IP而不知道其实是来自内部。

①在Internet上面的主机接到这个封包时,会将响应数据传送给那个Public IP的主机;
②当Linux NAT服务器收到来自Internet的回应封包后,会分析该封包的序号,并比对刚刚记录到内存当中的数据,由于发现该封包为后端主机之前传送出去的,因此在NAT Prerouting链中,会将目标IP修改成为后端主机,亦即192.168.1.100,然后发现目标已经不是本机(public IP),所以开始透过路由分析封包流向;
③封包会传送到192.168.1.2这个内部接口,然后再传送到最终目标192.168.1.100机器上去!经过这个流程,你就可以发现,所有内部LAN的主机都可以透过这部NAT服务器联机出去,而大家在Internet上面看到的都是同一个IP (就是NAT那部主机的public IP!),所以如果内部LAN主机没有连上不明网站的话,那么内部主机其实是具有一定程度的安全性的!因为Internet上的其他主机没有办法主动攻击你的LAN内的PC!所以我们才会说,NAT最简单的功能就是类似IP分享器!其也是SNAT的一种。
NAT服务器与路由器有啥不同?基本上NAT服务器一定是路由器,不过NAT服务器由于会修改IP表头数据,因此与单纯转递封包的路由器不同。最常见的IP分享器就是一个路由器,但是这个IP分享器一定会有一个Public IP与一个Private IP,让LAN内的Private IP可以透过IP分享器的Public IP传送出去!至于路由器通常两边都是Public IP或同时为Private IP。
SNAT主要是应付内部LAN连接到Internet的使用方式,至于DNAT则主要用在内部主机想要架设可以让Internet存取的服务器!有点类似DMZ内的服务器!

如上图所示,假设我的内部主机192.168.1.210启动了WWW服务,这个服务的port开启在port 80,那么Internet上面的主机 (61.xx.xx.xx) 要如何连接到我的内部服务器呢?还是得要透过Linux NAT服务器!所以这部Internet上面的机器必须要连接到我们的NAT的public IP才行。
①外部主机想要连接到目的端的WWW服务,则必须要连接到我们的NAT服务器上头;
②我们的NAT服务器已经设定好要分析出port 80的封包,所以当NAT服务器接到这个封包后,会将目标IP由public IP改成192.168.1.210,且将该封包相关信息记录下来,等待内部服务器的响应;
③上述的封包在经过路由后,来到private接口处,然后透过内部的LAN传送到192.168.1.210上头!
④192.186.1.210会响应数据给61.xx.xx.xx,这个回应当然会传送到192.168.1.2上头去;
⑤经过路由判断后,来到NAT Postrouting的链,然后透过刚刚步骤②的记录,将来源IP由192.168.1.210改为public IP后,就可以传送出去了!整个步骤几乎就等于SNAT的反向传送!
最阳春NAT服务器:IP分享功能在Linux的NAT服务器服务当中,最常见的就是IP分享器功能了,这个IP分享器的功能其实就是SNAT!作用就只是在iptables内的NAT表格当中,那个路由后的POSTROUTING链进行IP的伪装就是了。你的NAT服务器必须要有一个public IP接口,以及一个内部LAN连接的private IP界面才行。鸟哥的假设是这样的:
①外部接口使用eth0,这个接口具有public IP;
②内部接口使用eth1,假设这个IP为192.168.100.254。
当你设定你的网络参数后,务必要进行路由的检测,因为在NAT服务器的设定方面,最容易出错的地方就是路由!尤其是在拨接产生ppp0这个对外接口的环境下,这个问题最严重。你要记得:如果你的public IP取得的方式是拨接或cable modem时,你的配置文件/etc/sysconfig/network, ifcfg-eth0, ifcfg-eth1等档案,千万不要设定GATEWAY!否则就会出现两个default gateway,反而会造成问题。

重点在那个MASQUERADE !这个设定值就是 IP伪装成为封包出去 (-o) 的那块装置上的IP!以上面的例子来说,就是 E X T I F ,也就是 e t h 0 !所以封包来源只要来自 EXTIF,也就是eth0!所以封包来源只要来自 EXTIF,也就是eth0!所以封包来源只要来自innet(也就是内部LAN的其他主机),只要该封包可透过eth0传送出去,就会自动的修改IP的来源表头成为eth0的public IP!你只要将iptables.rule下载后,并设定好你的内、外网络接口,执行iptables.rule后,你的Linux就拥有主机防火墙以及NAT服务器的功能了!那你的LAN内的其他PC应该如何设定相关的网络参数?将NAT服务器作为PC的GATEWAY即可!只要记得底下的参数值:
①NETWORK为192.168.100.0
②NETMASK为255.255.255.0
③BROADCAST为192.168.100.255
④IP可以设定192.168.100.1 ~ 192.168.100.254间,不可重复!
⑤通讯闸 (Gateway) 需要设定为192.168.100.254 (NAT服务器的Private IP)
⑥DNS (/etc/resolv.conf) 需设定为168.95.1.1 (Hinet)或139.175.10.20 (Seed Net),这个依你的ISP而定。
除非你使用的是固定IP,且有多个IP可以对外联机,否则一般使用IP伪装即可,不需要使用到SNAT!
既然可以做SNAT的IP分享功能,我们当然可以使用iptables做出DMZ!但是不同的服务器封包传输的方式可能有点差异,因此建议新手不要玩这个!否则很容易导致某些服务无法顺利对Internet提供的问题。

服务器架设的步骤里,很重要的一点是你的主机名必须要在Internet上面可以被查询!这是因为人类对于IP记忆力不佳,所以才会以主机名来取代IP。你的主机名要能够被查询到才有用!这个时候一个合法的主机名就很重要!要合法的主机,就得要让DNS系统能够找的到你的主机!不过如果我们的主机是使用拨接得到的不固定IP,就得要使用动态DNS的系统
因为科技的发达,连上Internet的人们越来越多,使用/etc/hosts的方法已经搞不定了(只要一部新计算机上线,全部Internet上面的所有计算机都要重新改写/etc/hosts才行!)。这个时候领域名系统Domain Name System, DNS就适时出现了!DNS利用类似树状目录的型态,将主机名的管理分配在不同层级的DNS服务器当中,经由分层管理,所以每一部服务器记忆的信息就不会很多,而且异动上面也相当容易修改!DNS的功能就是将计算机主机的名称转译成IP就是了!总之它的最大功能就是让有意义的,人类较容易记忆的主机名(英文字母),转译成为计算机所熟悉的IP地址!DNS是个很庞大的架构,而且是串连在全球的网络当中,除非你经由注册的手续来让DNS系统承认你主机名存在的合法性,否则你架设的DNS只能说是一个地下练习的测试站而已,并没有用途。首先你必须要选择一个注册单位,并且检查出你想要注册的主机名是否存在?主机名是有意义的,并不是可以随便注册的!由于DNS查询的方式都是由上层的ISP提供解析授权给下游的注册者,因此下游的注册者只要设定妥当后,全世界的主机就会知道你设定的数据了。
①主机名的设计是有意义的,不可以随便设定
②主机名要生效,得要透过注册来取得合法授权。
预设的DNS转译是用在固定IP对应主机名的方法上面的!在这个情况下,你在DNS架构下申请完主机名后,如果你的IP不会更动,那就永远不用去烦恼主机名的相关问题,这也是所谓的静态DNS主机名功能。但我们的很多小网站都是以非固定IP来上网的,更有甚者,某些ADSL拨接模式甚至会定时强制断线,而每次拨接成功后取得的IP可不见得相同,如此一来IP一直在变。就需要一直跟上层DNS主机的管理员申请变更IP!所以现在为了解决这个问题,很多ISP提供了所谓的动态DNS服务功能,其是这样做的:
①Client端(就是你)每次开机或者是重新拨接,并取得一个新的IP之后,会主动向DNS Server端提出要求,希望Server端变更主机名与IP对应(这个步骤在每个主要的ISP都有提供适当的程序来提供给client使用);
②Server端接受Client端的要求之后,会先去查询Client提供的账号密码是否正确,若正确就会立即修改Server本身对于你的主机名的设定值。
所以每次我们取得新的IP之后,我们的主机名对应的IP也会跟着在DNS系统上面更新,如此一来,只要别人知道你的主机名,不论你的IP为何,它一定可以连上你的主机 (因为IP跟着你的主机而变!) 这对于我们这种使用动态IP的人是很有帮助的!
目前的主机名申请很多是需要钱的!如果你需要比较稳定的主机名对应IP的服务,那么花点钱来注册还是必须的。
静态DNS主机名注册:
①国外的领域名系统:http://wwwsol
②国外的领域名系统:http://www.dotster
③国外的领域名系统:http://www.godaddy
动态DNS主机名注册:免费的动态DNS系统主要就是这个NO-IP公司提供的网站:
①国外的免费DNS系统:http://www.no-ip
静态DNS的申请方式其实都差不多,都是需要:
①先查询所想要注册的网域是否存在;
②进入ISP去申请注册你所想要的主机名;
③缴费并等待主机名被启用。
动态DNS主机名注册:以no-ip为例:
①登入主网页http://www.no-ip并且注册一个新账号
②开始填写识别数据:由于启动账号必须由no-ip提供一个注册启动的连结,因此你必须要
填写正确的email来接受启动码。
③启用账号;
④登入no-ip且设定主机名与IP的对应;
⑤设定自动更新主机名与IP的对应。

# 1. 编译与安装
$ wget \
> http://www.no-ip/client/linux/noip-duc-linux.tar.gz
$ cd /usr/local/src
$ tar -zxvf /root/noip-duc-linux.tar.gz
$ cd noip*
$ make
$ make install
# 这样会将主程序安装在/sur/local/bin/noip2 而主参数档放在
# /usr/local/etc/no-ip2.conf 当中


接下来可以开始执行:

# 2. noip2的程序使用
$ /usr/local/bin/noip2
$ noip2 [-CS]
$ noip2 -S


这样就成功了,而且每30分钟noip2可以自动的去主网站上面进行更新!如果想要一开机就启动noip2,则这样做即可:

# 3. 设定开机启动
$ vim /etc/rc.d/rc.local
# 加入下面一行
/usr/local/bin/noip2


想象两种情况:
①如果你在工作单位使用的是笔记本电脑,而且常常要带着笔记本到处跑,那么连上Internet时会发现,网卡参数要常常修改。而且每到一个新的地方,就得问清楚该地的网络参数才行,非常麻烦。
②或者你的公司常常有访客或贵客来临,因为他们也带来笔计本,所以也得常常跑来找你问网络参数才能设定其计算机。
这个时候动态主机设定协议DHCP就派上用场!DHCP服务可以自动的分配IP与相关的网络参数给客户端,来提供客户端自动以服务器提供的参数来设定他们的网络。如此一来,使用者只要将自己的笔电设定好经由DHCP协议来取得网络参数后,一插上网线马上就可以享受Internet服务!
要设定好一个网络环境,使计算机可以顺利的连上Internet,那么你计算机里面一定要有底下几个网络参数才行,分别是:IP, netmask, network, broadcast, gateway, DNS IP,其中IP, netmask, network, broadcast与gateway都可以在/etc/sysconfig/networkscripts/ifcfg-eth[0-n]档案里面设定,DNS服务器的地址则在/etc/resolv.conf里头设定。只要这几个项目设定正确,那么计算机就可以上网了!如果你家里有3,4部计算机,你都可以手动来设定好所需的网络参数,然后利用NAT服务器功能,大摇大摆的连上Internet!
DHCP (Dynamic Host Configuration Protocol)服务器最主要的工作就是自动将网络参数正确的分配给网域中的每部计算机,让客户端计算机可以在开机的时候就立即自动的设定好网络参数值,这些参数值可以包括:IP、netmask、network、gateway与DNS的地址等。如此一来,身为管理员的你,只要注意到这一部提供网络参数的主机有没有挂掉就好,其他同学的个人计算机,DHCP主机已经完全都帮你搞定了!
DHCP通常是用于局域网络内的一个通讯协议,它主要藉由客户端传送广播封包给整个物理网段内的所有主机,若局域网内有DHCP服务器时,才会响应客户端的IP参数要求。所以DHCP服务器与客户端是应该要在同一个物理网段内的。至于整个DHCP封包在服务器与客户端的来来回回情况有点如下图:

客户端取得IP参数的程序可以简化如下
①客户端:利用广播封包发送搜索DHCP服务器的封包:若客户端网络设定使用DHCP协议取得IP (在Windows内为自动取得IP),则当客户端开机或者重新启动网卡时,客户端主机会发送出搜寻DHCP服务器的UDP封包给所有物理网段内的计算机。此封包的目标IP会是255.255.255.255,所以一般主机接收到这个封包后会直接予以丢弃,但若局域网内有DHCP服务器时,则会开始进行后续行为。
②服务器端:提供客户端网络相关的租约以供选择:DHCP服务器在接收到这个客户端的要求后,会针对这个客户端的硬件地址MAC与本身的设定数据来进行下列工作:
<1>到服务器的登录文件中寻找该用户之前是否曾经用过某个IP,若有且该IP目前无人使用,则提供此IP给客户端;
<2>若配置文件针对该MAC提供额外的固定IP (static IP)时,则提供该固定IP给客户端;
<3>若不符合上述两个条件,则随机取用目前没有被使用的IP参数给客户端,并记录下来。总之,服务器端会针对客户端的要求提供一组网络参数租约给客户端选择,由于此时客户端尚未有IP,因此服务器端响应的封包信息中,主要是针对客户端的MAC来给予回应。此时服务器端会保留这个租约然后开始等待客户端的回应。
③客户端:决定选择DHCP服务器提供的网络参数租约并回报服务器:由于局域网络内可能并非仅有一部DHCP服务器,但客户端仅能接受一组网络参数的租约。因此客户端必需要选择是否要认可该服务器提供的相关网络参数的租约。当决定好使用此服务器的网络参数租约后,客户端便开始使用这组网络参数来设定自己的网络环境。此外,客户端也会发送一个广播封包给所有物理网段内的主机,告知已经接受该服务器的租约。此时若有第二台以上的DHCP服务器,则这些没有被接受的服务器会收回该IP租约。至于被接受的DHCP服务器会继续进行底下的动作。
④服务器端:记录该次租约行为并回报客户端已确认的响应封包信息:当服务器端收到客户端的确认选择后,服务器会回传确认的响应封包,并且告知客户端这个网络参数租约的期限,并且开始租约计时!那该次租约何时会到期而被解约?你可以这样想:
<1>客户端脱机:不论是关闭网络接口(ifdown)、重新启动(reboot)、关机(shutdown)等行为,皆算是脱机状态,这个时候Server端就会将该IP回收,并放到Server自己的备用区中,等待未来的使用;
<2>客户端租约到期:前面提到DHCP server端发放的IP有使用的期限,客户端使用这个IP到达期限规定的时间,而且没有重新提出DHCP的申请时,就需要将IP交回去!这个时候就会造成断线。但用户也可以再向DHCP服务器要求再次分配IP。
以上就是DHCP这个协议在Server端与Client端的运作状态,由上面这个运作状态来看,只要Server端设定没有问题,加上Server与Client在硬件联机上面确定是OK的,那么Client就可以直接藉由Server来取得上网的网络参数。只要管理员能够正确的管理好DHCP服务器,那么上网的设定自然就变成一件很简单的事情!
不过关于上述的流程还有一些需要额外说明的:
①DHCP服务器给予客户端的IP参数为固定或动态:在上面的步骤里面,注意到步骤②,就是服务器会去比较客户端的MAC硬件地址,并判断该MAC是否需要给予一个固定的IP!所以我们可以设定DHCP服务器给予客户端的IP参数主要有两种:
<1>固定(Static) IP:只要那个客户端计算机的网卡不换掉,那么MAC肯定就不会改变,由于DHCP可以根据MAC来给予固定的IP参数租约,所以该计算机每次都能以一个固定的IP连上Internet!这种情况比较适合当这部客户端计算机需要用来做为提供区域内的一些网络服务的主机之用 (所以IP要固定)。
<2>动态(dynamic) IP:Client端每次连上DHCP服务器所取得的IP都不是固定的!都直接经由DHCP所随机由尚未被使用的IP中提供,除非你的局域网内的计算机有可能用来做为主机之用,所以必需要设定成为固定IP,否则使用动态IP的设定比较简单,而且使用上面具有较佳的弹性。假如你是一个ISP,而你只申请到150个IP来做为你的客户联机之用,但可以邀集200个使用者以上!例如开了一家餐馆,里面只有20个座位,那么是否一餐只能卖给20个人呢?因为客人是人来人往的,有人先吃有人后吃,所以同样是20个座位,但是可以有40个人来吃我的简餐,因为来的时间不一样!你的ISP虽然只有150个IP可以发放,但是因为使用者并非24小时都挂在线的,所以你可以将这150个IP做良好的分配,让200个人来轮流使用这150个IP!
如果我们观察上面DHCP运作模式的步骤④,会发现最后DHCP服务器还会给予一个租约期限!其实设定期限还是有优点的,最大的优点就是可以避免IP被某些使用者一直占用着,但该使用者却是Idle发呆的状态!例如我有150个IP,但偏偏我有200个用户。假设每个使用者都急着上网知道世足赛的消息,那么某些热门对战时段网络将可能达到使用尖峰!也就是这200个人同时要来使用这150个IP,这当然不可能,肯定会有50个人无法联机,这个时候租约到期的方式就很有用处了,那几个已经联机进来很久的人就会因为租约到期而被迫脱机,这个时候该IP就会被释放出来,先抢到先赢!所以那50个人 (包括被迫脱机的那个朋友) 只好继续的、努力的、加油的来进行DHCP要求!虽然说是优点,但其实如果站在使用者的角度来看,还是可能会造成公愤的!凭什么大家一起交钱,我先联机进来就需要先被踢出去。所以如果要当ISP,还是得要先规划好服务的方针才行!
既然有租约时间,那是否代表我用DHCP取得的IP就得要手动在某个时间点去重新取得新的IP呢?其实不需要,因为目前的DHCP客户端程序大多会主动的依据租约时间去重新申请IP (renew)!也就是说在租约到期前你的DHCP客户端程序就已经又重新申请更新租约时间了。所以除非DHCP主机挂点,否则你所取得的IP应该是可以一直使用下去的!一般来说,假设租约期限是T小时,那么客户端在0.5T会主动向DHCP服务器发出重新要求网络参数的封包。如果这次封包要求没有成功,那么在0.875T后还会再次的发送封包一次。正因如此,所以服务器端会启动port 67监听用户要求,而用户会启动port 68主动向服务器要求!
多部DHCP服务器在同一物理网段的情况:你可以会发现过一件事情,就是当网域里面有两部以上的DHCP服务器时,到底哪一部服务器会提供我这部客户端计算机所发出的DHCP要求?很抱歉确实不晓得!因为在网络上面,很多时候都是先抢先赢的,DHCP的回应也是如此!当Server1先响应时,你使用的就是Server1所提供的网络参数内容,如果是Server2先响应,你就是使用Server2的参数来设定你的客户端PC!不过前提当然是这些计算机的物理联机都是在一起。例如,某一次其他系的研究生在测试网络安全时,在原有的区网上面放了一部IP分享器,结果整栋大楼的网络都不通了,因为那时整栋大楼的网络是串接在一起的,而我们学校是使用DHCP让客户端上网。由于路由器的设定并不能连上Internet,大家就都无法上网了!不要随便测这个DHCP服务器。
①使用DHCP的几个时机:在某些情况下强烈的建议架设DHCP主机:
<1>具有相当多行动装置的场合:例如你公司内部很多笔记本电脑使用的场合。因为这种笔记本本身就是移动性装置,如果每到一个地方都要去问这边的网络参数是什么,还得要担心是否会跟别人的IP相冲突等问题,这个时候DHCP就是你的救星!
<2>区域内计算机数量相当多时:就是你所负责的网域内计算机数量相当庞大时,大到你没有办法一个一个的进行说明来设定它们自己的网络参数,这个时候为了省麻烦,还是架设DHCP来的方便。况且维护一部你熟悉的DHCP主机,要比造访几十个不懂计算机的人要简单的多!
②不建议使用DHCP主机的时机:回头看一下步骤①,客户端在开机的时候会主动的发送信息给网域上的所有机器,这个时候如果网域上就是没有DHCP主机,那么你的这部客户端计算机,仍然会持续的发送信息!真正的时间与次数不晓得会有多久,不过肯定会超过30秒以上,甚至可以达到一分钟以上!那么这段时间你只能除了等还是等!所以如果计算机数不多,还是使用手动的方式来设定一下就好。
<1>在你网域内的计算机,有很多机器其实是做为主机的用途,很少用户需求,那么似乎就没有必要架设DHCP;
<2>更极端的情况是,像一般家里只有3 ~ 4部计算机,这个时候架设DHCP只能拿来练练功力,事实上并没有多大的效益;
<3>当你管理的网域当中,大多数网卡都属于老旧的型号,并不支持DHCP协议时;
<4>很多用户的信息知识都很高,那么也没有需要架设DHCP。
目前市面上的路由器已经很便宜了,而路由器本身就含有DHCP功能。所以如果你只是想要单纯的在局域网中使用DHCP,那么建议你直接购买一部路由器来使用即可,因为至少它很省电。DHCP的软件需求很简单,就是只要服务器端软件即可,在Linux上面的软件就是dhcp!

一个局域网的DHCP服务器设定案例:假设在环境当中,Linux主机除了NAT服务器之外还得要负责其他服务器,例如邮件服务器的支持。而在后端局域网中则想要提供DHCP服务。则其Linux Router有两个接口,其中eth1对内而eth0对外,至于其他的网络参数设计为:
①Linux主机对内的eth1的IP设定为192.168.100.254;
②内部网段设定为192.168.100.0/24这一段,且内部计算机的router为192.168.100.254,此外DNS主机的IP为中华电信的168.95.1.1及Seednet的139.175.10.20这两个;
③我想要让每个使用者预设租约为3天,最长为6天;
④想要分配的IP只有192.168.100.101到192.168.100.200这几个,其他的IP则保留下来;
⑤我还有一部主机,它的MAC是08:00:27:11:EB:C2,给它的主机名设为win7,且IP为192.168.100.30。
则配置文件就会像下面这样:

$ vim /etc/dhcp/dhcpd.conf
# 1. 整体的环境设定
ddns-update-style none; # 不要更新DDNS的设定
ignore client-updates; # 忽略客户端的DNS更新功能
default-lease-time 259200; # 预设租约为3天
max-lease-time 518400; # 最大租约为6天
option routers 192.168.100.254; # 这就是预设路由
option domain-name "centos.vbird"; # 给予一个领域名
option domain-name-servers 168.95.1.1, 139.175.10.20;
# 上面是DNS的IP设定 这个设定值会修改客户端的/etc/resolv.conf档案内容

# 2. 关于动态分配的IP
subnet 192.168.100.0 netmask 255.255.255.0 {
    range 192.168.100.101 192.168.100.200; # 分配的IP范围
    # 3. 关于固定的IP
    host win7 {
        hardware ethernet 08:00:27:11:EB:C2; # 客户端网卡MAC
        fixed-address 192.168.100.30; # 给予固定的IP
    }
}


这样就设定好了!新版本的dhcp会主动的分析服务器的网段与实际的dhcpd.conf设定,如果两者无法吻合就会有错误提示,人性化多了。
开始启动dhcp!在启动前你得要注意几件事情
①你的Linux服务器网络环境已经设定好,例如eth1已经是192.168.100.254;
②你的防火墙规则已经处理好,例如:放行内部区网的联机、iptables.rule的NAT服务已经设定妥当;
另外你要注意的是:dhcpd使用的端口是port 67,并且启动的结果会记录在/var/log/messages档案内,你最好能去观察一下/var/log/messages所显示的dhcpd相关信息才好。

# 1. 启动后观察一下端口的变化
$ /etc/init.d/dhcpd start
$ chkconfig dhcpd on
$ netstat -tlunp | grep dhcp

# 2. 固定去看看登录文件的输出信息
$ tail -n 30 /var/log/messages


在使用DHCP之后,怎么知道哪一部PC连上我的主机,要怎么填写/etc/hosts的内容呢?可将所有可能的计算机IP都加进该档案即可。例如,鸟哥分配的IP至少有192.168.100.30, 192.168.100.101 ~ 192.168.100.200,所以/etc/hosts可以写成:

$ vim /etc/hosts


这样一来所有可能连进来的IP都已经有纪录了,不过更好的解决方案则是架设内部的DNS服务器,这样一来内部的其他Linux服务器也不必更改/etc/hosts就能够取得每部主机的IP与主机名对应,那样就更加妥当了。
DHCP客户端的设定
①客户端是Linux:

$ vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
NM_CONTROLLED=no
ONBOOT=yes
BOOTPROTO=dhcp # 就是它 指定这一个就对了
$ /etc/init.d/network restart


记得要拿掉预设路由的设定,改完之后将整个网络重新启动即可。如果执行的结果有找到正确的DHCP主机,那么几个档案可能会被更动:

# 1. DNS的IP会被更改 先查阅resolv.conf
$ cat /etc/resolv.conf
# 2. 观察一下路由
$ route -n
# 3. 查看一下客户端指令
$ netstat -tlunp | grep dhc
# 4. 看一看客户端租约所记载的信息
$ cat /var/lib/dhclient/dhclient*


②客户端是Windows:以Windows 7作为介绍,你可以依据『开始』–>『控制台』–>『检视网络状态及工作』 -->『变更适配卡设定』,在出现的图示中,选择属于你的相关网卡,然后连击两下之后,就开始底下的设定程序:



不过在Windows 2000以后,可能需要使用命令提示字符来观察才行。你可以使用:『开始』–>『所有程序』–>『附属应用程序』–>『命令提示字符』来取出终端机,然后这样处理看看:

如果你要管理的是几十部甚至是几百部的计算机时,你总是会希望能够根据座位来进行IP的给予,因此固定IP配合MAC就显的很重要!客户端会主动的记录租约信息,服务器端更不能忘记记录!服务器端是记录在这个地方:

$ cat /var/lib/dhcpd/dhcpd.leases


从这个档案里面我们就知道有多少客户端已经向我们申请了DHCP的IP使用了。
让大量PC都具有固定IP的脚本:如果你有一百台计算机要管理,每部计算机都希望是固定IP的情况下,可透过DHCP的fixed-address。既然每部计算机最终都得要开机,那么你在开机之后,利用手动的方法来设定好每部主机的IP后,再根据底下的脚本来处理好你的dhcpd.conf就可以了!

$ vim setup_dhcpd.conf
#!/bin/bash
read -p "Do you finished the IP's settings in every client (y/n)?" yn
read -p "How many PC's in this class (ex>60)" num
if ["$yn" = "y"]; then
    for site in $(seq 1 ${num})
    do
        siteip="192.168.100.${site}"
        allip="$allip $siteip"
        ping -c 1 -w 1 $siteip > /dev/null
        if ["$?" == "0"]; then
            okip="okip $siteip"
        else
            errorip="$errorip $siteip"
            echo "$siteip is DOWN"
        fi
    done
    [-f dhcpd.conf] && rm dhcpd.conf
    for site in $allip
    do
        pcname=pc$(echo $site | cut -d '.' -f 4)
        mac=$(arp -n | grep "$site " | awk '{print $3}')
        echo " host $pcname {"
        echo "         hardware ethernet ${mac};"
        echo "         fixed-address ${site};"
        echo " }"
        echo " host $pcname {"                    >> dhcpd.conf
        echo "         hardware ethernet ${mac};" >> dhcpd.conf
        echo "         fixed-address ${site};"    >> dhcpd.conf
        echo " }"                                 >> dhcpd.conf
    done
fi
echo "You can use dhcpd.conf (this directory) to modified your /etc/dhcp/dhcpd.conf"
echo "Finished."


这个脚本的想法很简单,如果你管理的计算机都是Linux的话,那么先开机后使用ifconfig
eth0 YOURIP来设定对应的IP,这里使用的是192.168.100.X/24这个区段,此时IP就设定好了!然后再透过上面的脚本跑一次,每部计算机的MAC与IP对应就顺利的写入dhcpd.conf。然后再将它贴上/etc/dhcp/dhcpd.conf即可!如果你管理的计算机是Windows的话,则使用文字接口下达netsh interface ip set address xxx之类的指令来修订!
使用ether-wake实行远程自动开机(remote boot):既然已经知道客户端的MAC地址了,如果客户端的主机符合一些电源标准,并且该客户端主机所使用之网卡和主板支持网络唤醒功能时,就可以透过网络来让客户端计算机开机了。如果你有一部主机想要让它可以透过网络来启动时,就必须要在这部客户端计算机上进行:
①首先要在BIOS里面设定网络唤醒功能,否则是没有用的!
②再来必须要让这部主机接上网线,并且电源也是接通的。
③将这部主机的MAC抄下来,然后关机等待网络唤醒。
接下来请到永远开着的DHCP服务器上面 (其实只要任何一部Linux主机均可!),安装net-tools这个软件后,就会取得ether-wake这个指令,这就是网络唤醒的主要功能!假设客户端主机的MAC为11:22:33:44:55:66并且与我的服务器eth1相连接好了,那么想要让这部主机被唤醒,就这样做:

$ ether-wake -i eth1 11:22:33:44:55:66
¥ ether-wake -u


然后就会发现那部客户端主机被启动了!以后如果你要连到局域网内的话,只要能够连上你的防火墙主机,然后透过这个ether-wake软件,就能够让你局域网内的主机启动了,管控上面就更加方便!
我们知道局域网络内如果很多Linux服务器时,你得要将private IP加入到每部主机的/etc/hosts里面,这样在联机阶段的等待时间才不会有逾时或者是等待太久的问题。如果计算机数量太大,又有很多测试机时,这时你得要常常去更新维护那些重灌过机器的/etc/hosts。此时在区网内架设一部DNS服务器负责主机名解析就很重要!因此既然已经有DNS服务器帮忙进行主机名的解析,那你根本不需要更动/etc/hosts!未来的新机器或者是新灌的计算机也不需要改写任何网络参数,这样维护会轻松很多。因此一个好的网域内,理论上我们应该在DHCP服务器主机上面再安装一个DNS服务器,提供内部计算机的名称解析为宜。
DHCP响应速度与网管switch的设定相关,主要表现为在重新启动网络取得DHCP时,都会等待几乎达30秒,虽然最终是成功的。取得IP之后,网络速度却又是正常的。大多在设定位于『L2 Features』–>『Spanning Tree』–>『STP Port Settings』的子项目之类的字眼,将STP之类的端口都设定为关闭Disabled,鸟哥做完这个设定后,DHCP的取得就顺畅了!STP主要的目的是在抵挡广播风暴,若侦测到广播风暴时,该switch的端口会被停用。只是启动这个功能后会较缓慢的进入运作状态,所以会产生较慢的情况发生。较好的switch会支援RSTP (Rapid spanning tree protocol),速度会较快一些。

代理服务器的功能是可以代理局域网络的个人计算机来向因特网取得网页或其他数据的一种服务,由于代理取得的数据可以保存一份在服务器的缓存上,因此以往有类似假象加速的功能!不过目前网络带宽已经比以前好很多,因此代理服务器倒是很少使用在这方面。代理服务器是用在应用层上的一种防火墙方式,Linux上启动代理服务器的是squid这个软件!
代理服务器Proxy的原理其实很简单,就是以类似代理人的身份去取得用户所需要的数据!但是由于它的代理能力,使得我们可以透过代理服务器来达成防火墙功能与用户浏览数据的分析!此外也可以藉由代理服务器来达成节省带宽的目的,以及加快内部网络对因特网的WWW访问速度。总之,代理服务器对于企业来说,实在是一个很不错的东西。
整个代理服务器与客户端的相关性如下图所示:

一般来说,代理服务器会架设在整个区网的单点对外防火墙上头,而在区网内部的计算机就都是透过Proxy来向因特网要求数据的,这就是所谓的代理服务器!上面的架构仅只是一个案例,其用的人比较多的原因是因为这样的Proxy server还可以兼做高阶防火墙之用。
在Proxy与客户端的相关性当中,你必需要了解的是:客户端向外部要求的资料事实上都是Proxy帮用户取得的,因此因特网上面看到要求数据者,将会是Proxy服务器的IP而不是客户端的IP。例如,假如鸟哥在浏览器设定了我们学校的代理服务器主机proxy.ksu.edu.tw做为Proxy,再假设我的IP是120.114.141.51,那么当我想要取得Yahoo的新闻信息时,都是proxy.ksu.edu.tw帮我去取得的,所以在Yahoo的网站上面看到要求数据的人当然就是proxy.ksu.edu.tw而不是120.114.141.51!Proxy还有一个很棒的额外功能,那就是防火墙功能,就是客户端的个人计算机要连上因特网一定要经过Proxy服务器。并且如果有人想要入侵你的系统时,由于你的proxy在最外部,所以攻击者就会攻击错方向,如此一来就比较安全!此外,由于整个因特网对外都是经过proxy,也就是单点对外的情况,这种状态底下要来管理防火墙也是比较简单的!
当客户端指定了代理服务器之后,在客户端想要取得因特网上面的信息时,它是这样取得数据的:
①当Proxy的缓存拥有用户所想要的数据时(Step a ~ d):
②Client端向Server端发送一个数据需求封包;
③Server端接收之后,先比对这个封包的来源与预计要前往的目标网站是否可接受?如果来源与目标都是合法的,或者说来源与目标网站我们的Proxy都能帮忙取得资料时,那么Server端会开始替Client取得资料。这个步骤中比较重要的就是比对政策,有点像是认证的感觉;
④Server首先会检查自己缓存 (新的数据可能在内存中,较旧的数据则放置在硬盘上) 数据,如果有Client所需的数据,那就将数据准备取出,而不经过向Internet要求数据的程序;
⑤最后当然就是将数据回传给Client端!
⑥当Proxy的缓存没有用户所想要的数据时 (Step 1 ~ 5):
⑦Client端向Server端发送一个数据需求封包;
⑧Server端接收之后,开始进行政策比对;
⑨Server发现缓存并没有Client所需要的资料,准备前往因特网抓取数据;
⑩Server开始向Internet发送要求与取得相关资料;
⑪最后当然就是将数据回传给Client端!
我们的Local proxy并不会主动的去捕捉数据,而是再透过上层代理服务器向Internet要求资料!由于可做为我们的上层代理服务器的主机通常是具有较高带宽的,因此我们透过它去要求数据当然理论上速度会更快,而上层代理服务器最大的好处其实是在于分流!

由于当用户透过Proxy连到因特网时,网络看到的是Proxy在抓取数据而不是该客户端,因此我们不难发现Proxy有可能会被客户端过度的滥用,同时也有可能会被拿来为非作歹!所以目前绝大部分的Proxy已经停止对外开放了,仅针对自己的网域内的用户提供本项服务而已。

如果想要共享档案,在Linux对Linux的环境下,最简单的方法就是透过NIS服务器。至于Windows对Windows的环境下,最简单的方法则是网络邻居。那如果你的区网中有Windows也有Linux而且想要共享文件系统的话该怎么办?那就使用Samba服务器!Samba可以让Linux加入Windows的网络邻居支持,让异质平台可以共享文件系统,Samba还可以让Linux上面的打印机成为打印机服务器(Printer Server)。

NFS为Network FileSystem的简称,它的目的就是想让不同的机器、不同的操作系统可以彼此分享个别的档案!目前在Unix Like当中用来做为文件服务器是相当不错的一个方案。基本上Unix Like主机连接到另一部Unix Like主机来分享彼此的档案时,使用NFS要比SAMBA这个服务器快速且方便的多。此外NFS的设定真的很简单,几乎只要记得启动Remote Procedure Call(RPC就是rpcbind这个软件),就一定可以架设的起来!如果是在Linux PC cluster的环境下,这个服务器被使用的机率更是高的多!

Tonido是一种可以在嵌入式设备上运行的云存储服务。它是为在SBC上运行而设计的,并且已经存在了很长一段时间,因此该软件已经成熟。使用Tonido,您可以存储、共享和流式传输文件,并且有适用于PC、Android和iOS的客户端。

总结

以上就是关于Linux和Windows操作系统基础功能要讲的内容,欢迎大家对本文章进行补充和指正。

参考资料

《鸟哥的Linux私房菜 基础学习篇》,人民邮电出版社出版
《鸟哥的Linux私房菜 服务器架设篇》,人民邮电出版社出版
《Operating Systems Foundations with Linux on the Raspberry Pi》,Arm Education Media
《高性能Linux服务器运维实战》,机械工业出版社

本文标签: 服务器 基础 系列 网络