用户和用户组

用户组指的是具有相同系统权限的一组用户,配置文件位于/etc/group。该配置文件的格式为组名:组密码占位符:组编号:组内用户名列表。当组内只有一个用户且用户名和组名相同的时候可以省略组内的用户名列表,例如:mysql:x:501:。组号1~499为系统预留的组编号。

/etc/shadow存放用户组的密码信息,和/etc/group一一对应。分别是组名称:组密码:组管理者:组中用户名列表。当组密码为空、星号或者感叹号的时候可以认为组密码为空.

/etc/passwd,存放用户信息。用户名:密码占位符:用户编号:用户组编号:用户注释信息:用户主目录:shell类型/etc/shadow存放用户密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ groupadd sexy # 添加组
$ groupmod -n market sexay # 组改名
$ groupmod -g 668 market # 更改组id
$ groupadd boss -g 666 # 创建用户组并同时指定gid
$ groupdel market # 删除用户组之前必须先删除组中的用户,否则成了黑户口可能有权限影响
$ groupadd sexy
$ useradd sdf -g sexy
$ useradd jzmb -g sexy
$ # 修改用户名
$ usermod -l cls sdf
$ usermod -d /home/cls cls
$ usermod -G sexy imooc # 将用户添加到组
$ userdel jzmb # 如果需要删除个人目录下,需要使用-r参数
$ passwd -l cls # 锁定账户
$ passwd -u cls # 解锁账户
$ gpasswd -a cls boss # 将cls用户添加到附属组boss,区别于useradd -g
$ useradd -g main_group -G group1,group2 # 创建用户并同时制定主组合附属组

创建用户的时候如果没有指定用户组,将会创建一个和用户名相同的用户组。建立/etc/nologin文件可以禁止除了root之外的所有用户登陆。id命令可以查看用户信息(用户名、用户编号;组编号、组列表),groups显示用户所在的组。

pem证书权限400。

1
gpasswd -a devel sudo # devel用户可以使用sudo运行部分命令

系统扫描和安全防范

主机扫描

主机扫描命令fping用于给目标主机发送ping请求,测试主机的存活情况。特点是并行发送,结果易读。ping实际上基于ICMP协议的,很多的运营商为了安全性屏蔽了ICMP封包,使用ping就无法准确知道主机是否存活。hping支持TCP/IP数据报组装。

make hping的时候如果遇到以下错误:

1
2
3
4
5
6
gcc -c -O2 -Wall    -g  main.c
main.c:29:18: 致命错误:pcap.h:没有那个文件或目录
#include <pcap.h>
^
编译中断。
make: *** [main.o] 错误 1

需要使用yum install -y libpcap-devel,make clean后再次make报错:

1
2
3
4
5
libpcap_stuff.c:19:21: 致命错误:net/bpf.h:没有那个文件或目录
#include <net/bpf.h>
^
编译中断。
make: *** [libpcap_stuff.o] 错误 1

执行ln -sf /usr/include/pcap-bpf.h /usr/include/net/bpf.h。make clean && make 报错如下:

1
2
3
/usr/bin/ld: cannot find -ltcl
collect2: 错误:ld 返回 1
make: *** [hping3] 错误 1

执行yum -y install tcl-devel。make clean && make 成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 对指定目标端口发起tcp探测(1.165机器上使用`sysctl -w net.ipv4.icmp_echo_ignore_all=1`写入内核参数可以忽略ICMP封包)
hping -p 3306 -S 192.168.1.165

# 伪造来源IP,模拟DDOS攻击
# 在165机器上执行`tcpdump -npi eth0 src host 192.168.1.128`抓取来自128的数据包
# 在128机器上执行`hping -p 3306 -S 192.168.1.165`,抓包如下:

05:15:11.885246 IP 192.168.1.128.dialog-port > 192.168.1.165.mysql: Flags [S], seq 25702362, win 512, length 0
05:15:11.885805 IP 192.168.1.128.dialog-port > 192.168.1.165.mysql: Flags [R], seq 25702363, win 0, length 0
05:15:12.885827 IP 192.168.1.128.h2250-annex-g > 192.168.1.165.mysql: Flags [S], seq 1159234257, win 512, length 0
05:15:12.886281 IP 192.168.1.128.h2250-annex-g > 192.168.1.165.mysql: Flags [R], seq 1159234258, win 0, length 0
05:15:13.886156 IP 192.168.1.128.amiganetfs > 192.168.1.165.mysql: Flags [S], seq 1926746266, win 512, length 0
05:15:13.886446 IP 192.168.1.128.amiganetfs > 192.168.1.165.mysql: Flags [R], seq 1926746267, win 0, length 0
05:15:14.886436 IP 192.168.1.128.rtcm-sc104 > 192.168.1.165.mysql: Flags [S], seq 877480920, win 512, length 0
05:15:14.886804 IP 192.168.1.128.rtcm-sc104 > 192.168.1.165.mysql: Flags [R], seq 877480921, win 0, length 0
05:15:15.886527 IP 192.168.1.128.zephyr-srv > 192.168.1.165.mysql: Flags [S], seq 92599202, win 512, length 0
05:15:15.886898 IP 192.168.1.128.zephyr-srv > 192.168.1.165.mysql: Flags [R], seq 92599203, win 0, length 0

# 我们在128机器上伪造ip 111.111.111.111向165发送数据`hping -p 3306 -S 192.168.1.165 -a 111.111.111.111`,165上使用`tcpdump -npi eth0 src host 111.111.111.111`,抓包如下:

05:20:47.637022 IP 111.111.111.111.cr-websystems > 192.168.1.165.mysql: Flags [S], seq 1736489811, win 512, length 0
05:20:48.637440 IP 111.111.111.111.precise-sft > 192.168.1.165.mysql: Flags [S], seq 1884271442, win 512, length 0
05:20:49.637893 IP 111.111.111.111.sent-lm > 192.168.1.165.mysql: Flags [S], seq 1138710010, win 512, length 0
05:20:50.638273 IP 111.111.111.111.attachmate-g32 > 192.168.1.165.mysql: Flags [S], seq 1280639165, win 512, length 0
05:20:51.638627 IP 111.111.111.111.cadencecontrol > 192.168.1.165.mysql: Flags [S], seq 964302270, win 512, length 0
05:20:52.638932 IP 111.111.111.111.infolibria > 192.168.1.165.mysql: Flags [S], seq 1582924875, win 512, length 0

# 如果发送发发送比较频繁会,服务器会多次建立TCP3次握手等待和重试,导致165机器多次重试并回包给128询问为什么128没有建立第三次握手。165一直无法收到第三次回应的包导致资源耗尽或者网卡流量拥堵。

路由扫描

Linux下traceroute默认发送udp包,而windows下tracert发送ICMP包,目标端口一般大于30000.traceroute支持3种协议(tcp,udp和ICMP,使用tcp的方式可以获得更加可靠的侦测)。

mtr测试主机到每一个路由的联通性。

以下是mtr github.com的结果:
mtr命令

我们可以看到各个节点的丢包还是比较严重的。

批量主机服务扫描

nmap

所谓的版开发是指不建立完整的TCP3次握手

1
2
$ nmap -sP 192.168.1.0/24 # 扫描主机段内哪些主机存活
$ nmap -sS -p 0-30000 192.168.1.165 # 发送SYN包,侦测主机服务,指定端口为0-30000

安全防范

SYN攻击的原理

攻击者伪造ip(利用hping)向目标主机发送SYN包,目标主机收到SYN=x包后,向操作系统内核的backlog队列中写入记录,并向不存在的地址回包SYN=y,ACK=x+1,服务器无法收到第三次握手包。如果攻击的ip很多,会一直想backlog中写入记录,导致backlog队列满了。由于无法收到第三次握手包,服务器会不断重试回包(带宽满),导致服务器一直处于等待,导致系统资源占满。

解决方案:

  • 减少发送SYN+ACK包的重试次数:
1
2
$ sysctl -w net.ipv4.tcp_synack_retires=3
$ sysctl -w net.ipv4.tcp_syn_retires=3
  • SYN Cookies技术

不建立3次握手,不做等待
sysctl -w net.ipv4.tcp_syncookies=1

  • 增加backlog队列长度

sysctl -w net.ipv4.tcp_max_syn_backlog=2048

其他补充策略:

  • 关闭ICMP:sysctl -w net.ipv4.icmp_echo_ignore_all=1
  • iptables防止恶意扫描:
1
2
3
$ iptables -A FORWARD -p tcp -syn -m limit -limit 1/s -limit-burst 5 -j ACCEPT
$ iptables -A FORWARD -p tcp -tcp-flags SYN,ACK,FIN,RST RST -m limit -limit 1/s -j ACCEPT
$ iptables -A FORWARD -p icmp -icmp-type echo-request -m limit -limit 1/s -j ACCEPT

iptables

NetFilter是linux操作系统核心层内部的一个数据包模块。Hook point是数据包在Netfilter中的挂载点(PRE_ROUTING,INPUT,OUTPUT,FORWARD,POST_ROUTING),数据包在经过这5个挂载点的时候我们可以进行处理。

NetFilter

iptables = 4张表(filter,nat,managle,raw) + 5条链(Hook Point) + 规则

Filter表:访问控制、规则匹配
Nat表:地址转发

数据包在4张表和5条链中的流向

iptables规则组成

数据包访问控制:ACCEPT,DROP,REJECT。DROP是直接丢包,REJECT是返回客户端拒绝消息
数据包改写:SNAT(改写原地址),DNAT(改写目标地址)
信息记录:LOG

iptables规则

场景1

  • 对所有地址开发本机TCP(80,22,10-21)端口访问。
  • 允许所有地址开放本机的基于ICMP协议的数据包访问。
  • 其他未被允许的端口禁止访问。

以下命令均在192.168.1.128上完成。

1
2
3
4
5
6
7
8
$ iptables -F # 清除规则
$ iptables -I INPUT -p tcp --dport 80 -j ACCEPT
$ iptables -I INPUT -p tcp --dport 22 -j ACCEPT # SSH端口要在默认的规则中加入
$ iptables -I INPUT -p tcp --dport 10:21 -j ACCEPT # 端口范围为10-21
$ iptables -I INPUT -p icmp -j ACCEPT # 允许ICMP协议
$ iptables -A INPUT -j REJECT # 拒绝其他端口,注意该规则追加在末尾
$ iptables -D INPUT -p tcp --dport 80 -j ACCEPT # 删除规则
$ iptables -I INPUT -p tcp -s 192.168.1.100 --dport 80 -j ACCEPT # 只允许192.168.1.100访问web服务

上面的规则中存在以下的几个问题:

  • 外部主机可以连接到22号端口,但是127.0.0.1(192.168.1.128上的)无法连接到22端口。(本机无法访问本机)
  • 本机无法向外发送请求,例如在192.168.1.128上执行curl http://www.baidu.com。(本机无法访问其他主机)
1
2
$ iptables -I INPUT -i lo -j ACCEPT # 开放本机lo网卡
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 已经建立TCP监听的时候放行

场景二

ftp主动模式客户端开放随机端口并使用PORT命令将该端口上传至服务器,服务器通过20端口向该随机端口推送数据。ftp被动模式是是客户端发送PASV命令给服务端,服务端会开放一个随机端口,并告诉客户端该端口,客户端会向服务端的该端口拉取数据。所谓的主动和被动是站在服务器的立场上说的。

ftp主动模式和被动模式

主动模式
被动模式

ftp默认使用的是被动模式。

vsftpd

在128服务器上进行如下iptables设置:

1
2
3
4
5
6
$ iptables -I INPUT -p tcp --dport 21 -j ACCEPT
$ iptables -I INPUT -p tcp --dport 22 -j ACCEPT
$ iptables -I INPUT -p icmp -j ACCEPT
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -A INPUT -j REJECT
$ iptables -nL

我们使用客户端进行登录,发现使用被动模式的时候连接被拒绝:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  ~ ftp anonymous@192.168.1.128
Connected to 192.168.1.128.
220 (vsFTPd 3.0.2)
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||53438|).
ftp: Can't connect to `192.168.1.128': Connection refused
200 EPRT command successful. Consider using EPSV.
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 6 Nov 05 19:43 pub
226 Directory send OK.
ftp>

在上面的图中我们发现设置了iptables规则后,ftp被动模式连接被拒绝,使用主动模式可以正常连接(服务器使用20端口向外发送数据)。但是ftp为什么默认是被动模式?这主要是为了安全考虑(使用固定的20端口发送数据可能被黑客拦截)。

编辑vsftpd配置文件:

1
2
3
# 开放被动模式的高端口
pasv_min_port=50000
pasv_max_port=60000

第一种方式:在上面的主动模式下的iptables上加上如下配置:

1
$ iptables -I INPUT -p tcp --dport 50000:60000 -j ACCEPT

可以发现我们已经可以使用ftp的被动模式了!

第二种方式:加入内核的连接追踪模块。

1
2
$ iptables -D INPUT -p tcp --dport 50000:60000 -j ACCEPT
$ modprobe nf_conntrack_ftp # 加入连接追踪模块

永久生效需要修改配置文件:/etc/sysconfig/iptables-config

1
IPTABLES_MODULES="nf_conntrack_ftp"

场景三

  • 员工在公司内部(192.168.1.0/24,192.168.2.0/24)能访问服务器上的任何服务
  • 员工出差(例如上海),通过VPN连接到公司外网(员工)->拨号到->VPN Server->内网ftp,samba,nfs,ssh
  • 公司有一个门户网站需要允许公网访问
1
2
3
4
5
6
7
8
9
$ iptables -F
$ iptables -I INPUT -i lo -j ACCEPT
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
$ iptables -A INPUT -s 192.168.2.0/24 -j ACCEPT
$ iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ iptables -A INPUT -p tcp --dport 1723 -j ACCEPT # VPN,pptp
$ iptables -I INPUT -p icmp -j ACCEPT
$ iptables -A INPUT -j REJECT

可以将以上脚本写入到/etc/rc.local开机启动项中/bin/sh /root/iptables_rules.sh

iptables NAT表配置

  • SNAT:源地址转换,出口POSTROUTING
  • DNAT:目的地址转换,入口PREROUTING

SNAT网络拓扑结构

以上的结构中101为宿主机,NAT Server2个网卡(hostonly + bridge)。

在NAT Server上进行如下配置:

1
2
3
4
5
6
7
$ vi /etc/sysctl.conf
net.ipv4.ip_forward=1

$ sysctl -p # load value from file
$ sysctl -a | grep ip_forward # check if valid
$ iptables -t nat -A POSTROUTING -s 172.16.61.0/24 -j SNAT --to 192.168.1.128 # 将源地址改写
$ iptables -t nat -L

在客户机172.16.61.129上加入默认网关

1
2
$ netstat -rn # 查看路由表
$ route add 0.0.0.0 gw 172.16.61.128

DNAT

1
$ iptables -t nat -A PREROUTING -d 192.168.1.128 -p tcp --dport 80 -j DNAT --to 172.16.61.129:80

iptables防CC攻击

connlimit模块用于限制每个客户端ip的并发连接数。

1
2
$ iptables -F
$ iptables -I INPUT -p TCP --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT # 每个客户端ip连接不能超过100

limit模块用于限速和控制流量。

1
2
3
# 10个包之类放行,超过10个的时候仅允许每分钟1个
$ iptables -A INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT
$ iptables -A INPUT -p icmp -j DROP # 关掉默认的ICMP

使用iptables进行端口转发实现nginx代理功能

1
2
# 当访问80端口的时候将流量转发到8080端口
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

SSH免密登陆

关闭root登陆,密码登陆可以提升服务器安全性。ssh免密登陆,将公钥粘贴到服务器的~/.ssh/authorized_keys,并设置权限为600。重启ssh服务。

Fail2Ban软件可以对服务器安全进行记录。