从 ArchLinux 的网络配置看 KISS 原则 RedHat 与 Archlinux 网络配置策略心得

ArchLinux Bash CentOS DHCP DNS HTTP IP SSH TCP UDP Ubuntu Windows grep kill 网络 路由 操作系统

最近在实验室配置网络和服务器,尤其是在RedHat EL上的网络配置,让我对ArchLinux的KISS原则体会颇深。

我在p大信科的实验室,包括楼下的机房和楼上的办公室。机房有一台H3C ER路由器和一台交换机,办公室也是一个路由器、一个交换机,加两个WiFi。机房有两根线接上来。

在不得不重置路由器(第一次用Console-COM接口)之后,终于把整个网络配置起来,包括域名、DHCP、与机房的互联与权限(这是教育网的独特之处)控制。Windows一直有人在维护,我负责把机房的两台RedHat配置起来。麻烦在于我只知道这两台机器是RedHat,其他一无所知。

重置密码成功

当然,首先要重置root密码。重启、进入grub、编辑启动项、选择并编辑内核参数、最后加一个1、启动并进入单用户模式。然后的操作就熟为人知了:重置root密码,添加用户并加入sudoers

passwd
useradd harttle -g wheel
passwd harttle
vim /etc/sudoers # 允许wheel group
exit

根据archlinux来的习惯,我甚至准备yum install vim sudoers。惊喜地发现这些软件RHEL都内置了,也许编辑sudoers也并非必要。像centOS一样,一经安装便是一个完整的服务器操作系统,而且提供长期维护的版本,确实是服务器的绝佳选择。

此时我已经是管理员用户了,那么在系统启动后登录我的账号,一眼就认出来四年前见过的Gnome,怀旧的情愫油然而生。接下来配置网络!

配置DHCP失败

懒得找从哪里打开console,于是Ctrl+Alt+F1打开TTY1,居然是不响应键盘的启动log!然后继续Ctrl+Alt+F2打开TTY2,OK,登录。然后习惯性地开始配置网络:

ip link
ip link set eth0 up
ip addr add 192.168.x.x dev eth0
ip link set eth0 netmast 255.255.255.0 broadcast 192.168.1.255

这样设置好IP与掩码之后才会与路由器位于同一网段,才能登录到路由器。ArchLinux中甚至没有内置ifconfig(在net_tools中)和iwconfig(在wireless_tools中),因为ip就可以完成所有配置呀!ArchLinux就是这么名副其实的Simple。

接着用firefox去路由器,绑定静态DHCP。然后呢,就来通过DHCP来获得地址吧:

$ dhcpcd eth0
Command dhcpcd not found
$ ps aux | grep dhcp    # 没有~~~~(>_<)~~~~ 
$ dhc <Tab> <Tab>
$ dhclient eth0         # 原来是这样
$ ip addr               # 仍然没分配到地址

如果这时候你希望从Gnome桌面的网络连接模块里得到信息的话,我告诉你里面甚至连本地连接接口都没有!不要使用GUI做系统管理。

来,开始排错!Ctrl+Alt+F3打开TTY3,监听DHCP报文:

tcpdump -n -i eth0 port 67 or port 68

回到TTY2,再来一次dhclient eth0,提示已经在运行。哦,原来是后台进程,ps出来kill掉。再来一次dhclient eth0,提示已发送信号给DHCP客户端守护进程,同时TTY3没有任何响动。擦,是后台进程但不是守护进程!总之 dhclient并未发送DHCP报文,也没有提示错误或者警告

在ArchLinux中dhcpcd是DHCP客户端守护进程,每次命令的调用都会发送一次DHCP报文,立竿见影。

配置SSH失败

没办法,就用现在的静态IP继续设置sshd,这样我就可以远程操作了!

vim /etc/ssh/sshd_config
# 禁止root用户登录、检查端口是否正确、设置AliveInteval、AllowUsers、etc。

在路由器映射22号端口后测试ssh!在本地ssh harttle@localhost登录成功!ssh harttle@<路由器公网IP>连接失败!同时tcpdump port 22可以看到收到了路由器转发来的SSH报文,难道是路由表?

vim /etc/sysconfig/iptables
# 检查filter是否REJECT了eth0上与ssh有关的包

路由表没问题,试着重启service iptables restart,仍不起作用。到此为止,回家睡觉!

按照RedHat的习惯重新配置

第二天,对上述的失败反思了很久。用了这么久的ArchLinux,相信如上的命令没有问题。来一本鸟哥,学习一下CentOs,毕竟和RedHat是一样的源码。读后恍然大悟:

vim /etc/sysconfig/network-scripts/ifcfg-eth0
# 发现这里是原来管理员的设置,静态IP与静态路由,但开启了dhcp,改正之。
/etc/init.d/network restart
# 一切都好了。DHCP正常、SSH连接成功。

原来RedHat是这样配置的。确实Simple,满足服务器操作系统的一大需求。 为什么这样Simple却花费了我如此多的功夫呢?我的命令也正确为什么没有得到应有的结果?这正是因为RedHat并无KISS原则

Keep it simple, stupid.

首先,根据RFC-2131,DHCP作为局域网内的协议,其功能是:为主机提供Internet配置。在多数实现中该配置都包括了IP、掩码、广播、DNS、路由。然而dhclient未能将得到的这些字段都进行设置,因为/etc/sysconfig/network-scripts/ifcfg-eth0是这样配置的:

...
BOOTPROTO=dhcp
IPADDR=192.168.1.72
NETMASK=255.255.255.0
GATEWAY=192.168.1.2

这里的路由是192.168.1.2,导致sshd可以接收到SSH报文,但却发送不出去。于是局域网内可以SSH(根据RFC791的IP协议,此时不经过路由,而是通过ARP来直接寻找MAC地址),但不能通过局域网的路由从外部访问。

严格地说该配置是有误的。开启DHCP,却指定了静态网络配置。RedHat没有抱怨而是选择了容错,这样的策略使得网络配置更加灵活,例如可以部分设置采用DHCP;但造成了dhclient命令没有达到预期的结果。其原因很简单, 该策略比较complex,不满足simple原则

其次,dhclient只是发送信号给守护进程,而不保证执行用户的意图:发送DHCP报文。这样的设计虽然通过更复杂的逻辑避免了额外的payload,其后果就是未能执行承诺的操作。原因仍然很显然, 这样的策略比较smart,不满足stupid原则 。让你发DHCP你就发DHCP,自作聪明地忽略该操作将会让tcpdump无法追溯到出了什么问题!

RedHat 服务器配置

既然装好了,把常用的配置都记录一下,以免今后忘记。我这里的版本是RedHat6.3。

yum源

众所周知CentOS是基于RedHat的源文件开发的,因此如果你不想支付数千元给红帽,就是用CentOS的源。

所谓源不就是软件包的获取地址,相同平台上系统,具有相同的系统调用,自然软件包是通用的。

教育网源对教育网用户是最方便的,这个ustc的源就很好。拷过来!

ustc的Ubuntu源就非常好,不知p大何时能赶上这些学校的思想?开源和合作必将是软件开发的潮流。

因为RedHat和CentOS的$releasever产生方式不一样,会导致源的url有区别,结果就是获取源时发生HTTP404。进入/etc/yum.conf/etc/yum.repos.d/rhel-source.repo,用vim替换一下~(:%s/\$releasever/6/g

然后更新:

yum clean all
yum makecache
yum -y update

VPN 或代理

众所周知,我们有服务器,当然希望提供代理或者VPN,以供我们更好地利用Internet。

VPN协议有多种,而pptp、l2tp需要路由器支持。当然可以使用openVPN等上层协议的VPN工具,其代价便是客户端都需要安装特定的程序。于是我们决定使用代理服务器,自然会选择最流行的squid。

而普通路由器之所以能让多台主机共享互联网IP,依赖于其NAT地址转换。NAT地址转换需要用到TCP/UDP的端口字段。pptp是直接运行在IP层之上的协议,并无端口字段,一些路由器可以利用它的其他无用字段来实现NAT穿透,于是pptp协议需要特殊的路由器。

更改路由表的filter表,即RedHat防火墙:

# file: /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3128 -j ACCEPT

安装squid后,配置squid:

# file: /etc/squid/squid.conf
http_access allow all

启动squid:

# 开机启动
chkconfig squid on
# 启动
service squid start

再通过路由器的端口映射就可以使用了。

Harttle

致力于简单的、一致的、高效的前端开发

看看这个?