1
2
3
4
git rm -r --cached .  # 不删除本地文件
git rm -r --f .    # 删除本地文件
git rm --cached 1.txt # 删除readme1.txt的跟踪,并保留在本地。
git rm --f 1.txt # 删除readme1.txt的跟踪,并且删除本地文件。

已经被纳入了版本管理中,则修改 .gitignore 是无效的。

解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

1
2
3
4
5
git rm -r --cached .
git add .

# 提交暂存区到本地仓库中
git commit -m 'update .gitignore'

自定义函数

自定义函数规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号 : 起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
    阅读全文 »

条件语句

if、elif、else 来进行逻辑判断

格式:

1
2
3
4
5
6
7
8
if 判断条件1:
执行语句1...
elif 判断条件2:
执行语句2...
elif 判断条件3:
执行语句3...
else:
执行语句4...
阅读全文 »

GRANT语法

在 MySQL 中,拥有 GRANT 权限的用户才可以执行 GRANT 语句,其语法格式如下:

1
2
3
4
GRANT priv_type [(column_list)] ON database.table
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user[IDENTIFIED BY [PASSWORD] 'password']] ...
[WITH with_option [with_option]...]

实例:

1
2
3
4
GRANT SELECT,INSERT,DELETE,UPDATE ON *.* TO 'root'@'192.125.30.123' IDENTIFIED BY '123456' WITH GRANT OPTION;

# 刷新
FLUSH PRIVILEGES;

取消权限:

revoke all on *.* from root@localhost;

  • priv_type 参数表示权限类型;
  • columns_list 参数表示权限作用于哪些列上,省略该参数时,表示作用于整个表;
  • database.table 用于指定权限的级别;
  • user 参数表示用户账户,由用户名和主机名构成,格式是“‘username‘@’hostname’”;
  • IDENTIFIED BY 参数用来为用户设置密码;
  • password 参数是用户的新密码。

WITH 关键字后面带有一个或多个 with_option 参数。这个参数有 5 个选项,详细介绍如下:

  • GRANT OPTION:被授权的用户可以将这些权限赋予给别的用户;
  • MAX_QUERIES_PER_HOUR count:设置每个小时可以允许执行 count 次查询;
  • MAX_UPDATES_PER_HOUR count:设置每个小时可以允许执行 count 次更新;
  • MAX_CONNECTIONS_PER_HOUR count:设置每小时可以建立 count 个连接;
  • MAX_USER_CONNECTIONS count:设置单个用户可以同时具有的 count 个连接。

GRANT 语句中可用于指定权限级别的值有以下几类格式:

  • *:表示当前数据库中的所有表。
  • *.*:表示所有数据库中的所有表。
  • db_name.*:表示某个数据库中的所有表,db_name 指定数据库名。
  • db_name.tbl_name:表示某个数据库中的某个表或视图,db_name 指定数据库名,tbl_name 指定表名或视图名。
  • db_name.routine_name:表示某个数据库中的某个存储过程或函数,routine_name 指定存储过程名或函数名。
  • TO 子句:如果权限被授予给一个不存在的用户,MySQL 会自动执行一条 CREATE USER 语句来创建这个用户,但同时必须为该用户设置密码。

数据库权限的权限类型

权限名称 对应user表中的字段 说明
SELECT Select_priv 表示授予用户可以使用 SELECT 语句访问特定数据库中所有表和视图的权限。
INSERT Insert_priv 表示授予用户可以使用 INSERT 语句向特定数据库中所有表添加数据行的权限。
DELETE Delete_priv 表示授予用户可以使用 DELETE 语句删除特定数据库中所有表的数据行的权限。
UPDATE Update_priv 表示授予用户可以使用 UPDATE 语句更新特定数据库中所有数据表的值的权限。
REFERENCES References_priv 表示授予用户可以创建指向特定的数据库中的表外键的权限。
CREATE Create_priv 表示授权用户可以使用 CREATE TABLE 语句在特定数据库中创建新表的权限。
ALTER Alter_priv 表示授予用户可以使用 ALTER TABLE 语句修改特定数据库中所有数据表的权限。
SHOW VIEW Show_view_priv 表示授予用户可以查看特定数据库中已有视图的视图定义的权限。
CREATE ROUTINE Create_routine_priv 表示授予用户可以为特定的数据库创建存储过程和存储函数的权限。
ALTER ROUTINE Alter_routine_priv 表示授予用户可以更新和删除数据库中已有的存储过程和存储函数的权限。
INDEX Index_priv 表示授予用户可以在特定数据库中的所有数据表上定义和删除索引的权限。
DROP Drop_priv 表示授予用户可以删除特定数据库中所有表和视图的权限。
CREATE TEMPORARY TABLES Create_tmp_table_priv 表示授予用户可以在特定数据库中创建临时表的权限。
CREATE VIEW Create_view_priv 表示授予用户可以在特定数据库中创建新的视图的权限。
EXECUTE ROUTINE Execute_priv 表示授予用户可以调用特定数据库的存储过程和存储函数的权限。
LOCK TABLES Lock_tables_priv 表示授予用户可以锁定特定数据库的已有数据表的权限。
ALL 或 ALL PRIVILEGES 或 SUPER Super_priv 表示以上所有权限/超级权限

表权限的权限类型

权限名称 对应user表中的字段 说明
SELECT Select_priv 授予用户可以使用 SELECT 语句进行访问特定表的权限
INSERT Insert_priv 授予用户可以使用 INSERT 语句向一个特定表中添加数据行的权限
DELETE Delete_priv 授予用户可以使用 DELETE 语句从一个特定表中删除数据行的权限
DROP Drop_priv 授予用户可以删除数据表的权限
UPDATE Update_priv 授予用户可以使用 UPDATE 语句更新特定数据表的权限
ALTER Alter_priv 授予用户可以使用 ALTER TABLE 语句修改数据表的权限
REFERENCES References_priv 授予用户可以创建一个外键来参照特定数据表的权限
CREATE Create_priv 授予用户可以使用特定的名字创建一个数据表的权限
INDEX Index_priv 授予用户可以在表上定义索引的权限
ALL 或 ALL PRIVILEGES 或 SUPER Super_priv 所有的权限名

列权限的权限类型

值只能指定为 SELECT、INSERT 和 UPDATE,同时权限的后面需要加上 列名 列表 column-list

用户权限类型

1
2
3
4
5
6
7
8
# 创建新的用户,并授予 数据有查询、插入权限,并授予 GRANT 权限
GRANT SELECT,INSERT SLAVE ON *.* TO 'slave'@'localhost' identified by '123456' WITH GRANT OPTION;

# 查询用户权限
SHOW GRANTS FOR 'slave'@'localhost';

# 刷新
FLUSH PRIVILEGES;

IPv4查看

cat /proc/net/sockstat

1
2
3
4
5
6
sockets: used 230
TCP: inuse 30 orphan 0 tw 2 alloc 36 mem 2
UDP: inuse 3 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

说明:

  • sockets: used:已使用的所有协议套接字总量
  • TCP: inuse:正在使用(正在侦听)的TCP套接字数量。其值≤ netstat –lnt | grep ^tcp | wc –l
  • TCP: orphan:无主(不属于任何进程)的TCP连接数(无用、待销毁的TCP socket数)
  • TCP: tw:等待关闭的TCP连接数。其值等于netstat –ant | grep TIME_WAIT | wc –l
  • TCP:alloc(allocated):已分配(已建立、已申请到sk_buff)的TCP套接字数量。其值等于netstat –ant | grep ^tcp | wc –l
  • TCP:mem:套接字缓冲区使用量(单位不详。用scp实测,速度在4803.9kB/s时:其值=11,netstat –ant 中相应的22端口的Recv-Q=0,Send-Q≈400)
  • UDP:inuse:正在使用的UDP套接字数量
  • RAW:
  • FRAG:使用的IP段数量

IPv6查看

cat /proc/net/sockstat6

1

TCP 报文格式简介

  • TCP 报文由 TCP HeaderTCP 数据组成。
  • TCP Header 的最大长度为 60 字节(byte),而必须要有的固定长度也就是图一的前5层的**20字节(byte),每层占有 32bit,也就是 32/8=4 字节,5层,5*4 = 20 字节,那么第六层的可选项和填充也就是Tcp Options字段最大为60-20=40字节(byte)**。填充是为了使TCP首部为4字节(32bit)的整数倍。

TCP首部格式

2964446-ab077ff3902529a3.webp

Source Port:源端口,16位(bit),2个字节(byte)。
Destination Port:目的端口,16位,2个字节。
Sequence Number:序号,发送数据包中的第一个字节的序列号,32位。
Acknowledgment Number:确认序列号,32位。
Data Offset:数据偏移,4位,该字段的值是TCP首部(包括选项)长度除以4。
标志位:6位,共6个标志位
URG 表示 Urgent Pointer 字段有意义
ACK 表示 Acknowledgment Number 字段有意义
PSH 表示 Push 功能,RST 表示复位 TCP 连接
RST 表示连接复位请求
SYN 表示 SYN 报文(在建立 TCP 连接的时候使用)
FIN 表示没有数据需要发送了(在关闭 TCP 连接的时候使用)
Window:窗口,表示接收缓冲区的空闲空间,16位,2个字节,用来告诉TCP连接对端自己能够接收的最大数据长度。
Checksum:校验和,16位,2个字节。
Urgent Pointers:紧急指针,16位,2个字节,只有 URG 标志位被设置时该字段才有意义,表示紧急数据相对序列号(Sequence Number字段的值)的偏移。
选项和填充:最常见的可选字段是最长报文大小,又称为 MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
数据:TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

TCP Options字段

Tcp Options 字段的最大长度为40字节。Tcp Options 字段的一般数据结构如图所示:

  • Kind(1字节)
  • Length(1字节)
  • Info(n字节)

选项的第一个字段 kind 说明选项的类型。有的 TCP 选项没有后面两个字段,仅包含1字节的kind字段。第二个字段length(如果有的话)指定该选项的总长度,该长度包括kind字段和length字段占据的2字节。第三个字段 info(如果有的话)是选项的具体信息。

tcpoptions.png

  • 第一个kind= 2,表示最大报文段长度(Max Segment Size,MSS),TCP 模块通常将 MSS 设置为(MTU-40, MTU[Maximum Transmission Unit,缩写 MTU,中文名是:最大传输单元])字节(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。这样携带 TCP 报文段的IP数据报的长度就不会超过 MTU(假设TCP头部和IP头部都不包含选项字段,并且这也是一般情况),从而避免本机发生IP分片。对以太网而言,MSS 值是1460(1500-40)字节。
  • kind= 4,表示支持 SACK,SACK Block(收到乱序数据)。
  • kind = 8,代表 Timestamps,即时间戳,启用 Timestamp Option 后,每个 TCP Segment 中都会带有 Timestamp Option,其中包含了两个 32bit 的 Timestamp 也就是各四个字节的 Timestamp Value(TSval)和 Timestamp Echo Reply(TSecr)。发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方在确认该报文段时把时间戳字段值复制到时间戳回送回答字段。因此,发送方在收到确认报文后,可以准确计算出RTT。

TCP标志位

在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG。其中,对于我们日常的分析有用的就是前面的五个字段。

SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有 DATA数据传输,RST表示连接重置。

ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应,如果只是单个的一个SYN,它表示的只是建立连接。
TCP的几次握手就是通过这样的ACK表现出来的。但SYN与FIN是不会同时为1的,因为SYN表示的是建立连接,而FIN表示的是断开连接。
RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。
一般地,当出现FIN包或RST包时,我们便认为客户端与服务器端断开了连接;而当出现SYN和SYN+ACK包时,我们认为客户端与服务器建立了一个连接。
PSH为1的情况,一般只出现在DATA内容不为0的包中,也就是说PSH为1表示的是有真正的TCP数据包内容被传递。

SYN:同步标志

同步序列编号(Synchronize Sequence Numbers)栏有效,表示同步序号,用来建立连接。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。TCP序列编号是一个范围从 0~4294967295 (2^32-1) 的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK= 1;

这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求-连接-严格进行的TCP三次握手;

初始化序列号生成过程:

RFC1948中提出了一个较好的初始化序列号ISN随机生成算法。

ISN = M + F(localhost, localport, remotehost, remoteport).
M是一个计时器,这个计时器每隔4毫秒加1。
F是一个Hash算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。要保证hash算法不能被外部轻易推算得出,用MD5算法是一个比较好的选择。
ISN会和一个假的时钟绑在一起,这个时钟M会在每4微秒对ISN做加一操作,直到超过 2^32,又从0开始。这样,一个ISN的周期大约是4.55个小时。因为,我们假设我们的TCP Segment在网络上的存活时间不会超过Maximum Segment Lifetime(缩写为MSL),所以,只要MSL的值小于4.55小时,那么,我们就不会重用到ISN。

ACK:确认标志

确认编号(Acknowledgement Number)栏有效。此标志表示应答域有效;有两个取值:0和1,为1的时候表示应答域有效,反之为0。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

RST:复位标志

这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;

URG:紧急标志

此标志表示TCP包的紧急指针域有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据;

PSH:推标志

这个标志位表示Push操作,该标志置位时,指在数据包到达接收端以后,接收端不将该数据进行队列处理,立即传送给应用程序,而不是在缓冲区中排队。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的。

FIN:结束标志

表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。当一个FIN标志的TCP数据包发送到一台计算机的特定端口,如果这台计算机响应了这个数据,并且反馈回来一个RST标志 的TCP包,就表明这台计算机上没有打开这个端口,但是这台计算机是存在的;如果这台计算机没有反馈回来任何数据包,这就表明,这台被扫描的计算机存在这个端口。

工作方式

建立连接

tcp1

TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出 SYN 连接请求后,等待对方回答 SYN+ACK,并最终对对方的 SYN 执行 ACK 确认。

TCP三次握手的过程如下:

  • 客户端发送 SYN(SEQ=x) 报文给服务器端,进入 SYN_SEND 状态。
  • 服务器端收到 SYN 报文,回应一个 SYN (SEQ=y)ACK(ACK=x+1) 报文,进入 SYN_RECV 状态。
  • 客户端收到服务器端的 SYN 报文,回应一个 ACK(ACK=y+1) 报文,进入 Established(已获确认的) 状态。

三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。

连接终止

tcp3.gif

建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的 半关闭half-close)造成的。

  • (1)某个应用进程首先调用 close,称该端执行 主动关闭(active close)。该端的TCP于是发送一个 FIN 分节,表示数据发送完毕。
  • (2) 接收到这个 FIN 的对端执行 被动关闭(passive close),这个 FIN 由TCP确认。

注意:FIN 的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN 的接收意味着接收端应用进程在相应连接上再无额外数据可接收。

  • (3) 一段时间后,接收到这个文件结束符的应用进程将调用 close 关闭它的套接字。这导致它的 TCP 也发送一个 FIN
  • (4) 接收这个最终 FIN 的原发送端TCP(即执行主动关闭的那一端)确认这个 FIN

既然每个方向都需要一个FIN和一个 ACK ,因此通常需要4个分节。

注意:
(1) 通常 是指,某些情况下,步骤1的 FIN 随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。
(2) 在 步骤2 与 步骤3 之间,从执行 被动关闭一端 到 执行主动关闭一端 流动数据是可能的,这称为 半关闭(half-close)。
(3) 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN
无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。

TCP重连

tcp重连.png

四元组:源IP地址、目的IP地址、源端口、目的端口
五元组:源IP地址、目的IP地址、协议号、源端口、目的端口
七元组:源IP地址、目的IP地址、协议号、源端口、目的端口、服务类型、接口索引

状态详解

  1. CLOSED:表示初始状态。

  2. LISTEN:表示服务器端的某个SOCKET处于监听状态,可以接受连接了。

  3. SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

  4. SYN_SENT: 这个状态与SYN_RCVD呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

  5. ESTABLISHED:表示连接已经建立了。

  6. FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

  7. FIN_WAIT_2:FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

  8. TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

  9. CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK 报文,再收到对方的 FIN 报文。但是 CLOSING 状态表示你发送 FIN 报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

  10. LAST_ACK:它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

参考:

Tcp报文简介以及头部选项字段(Tcp Options字段)

常用的TCP Option

TCP协议中的序列号

TCP标志位详解

浅析TCP中时间戳选项timestamp

简介

TcpDump 使用了独立于系统的 libpcap 的接口。libpcap 是linux平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础。tcpdump 调用libpcap 的接口在 linux 系统链路层抓包。而linux本身指定的许多访问控制规则都是基于三层或三层以上的过滤规则,所以 tcpdump 可以抓取过滤规则之前的数据包。使用tcpdump 需要有root权限。

网卡基础知识

网卡的不同接受模式

  • 广播模式:该模式下网卡能接收网络中的广播信息。
  • 组播模式:该模式下网卡能接收网络中的组播信息。
  • 直接模式:该模式下网卡能接收网络中目的地址为自己的数据包。
  • 混杂模式:该模式下网卡能接收网络中一切通过该网卡的数据包。

注:网卡混杂模式:是网卡的一种工作模式,一般在抓取网卡数据包时使用。

1
2
3
4
device eth0 entered promiscuous mode # 是指网卡 eth0 进入了混杂模式。
device eth0 left promiscuous mode # 网卡 eth0 离开了混杂模式。
ifconfig eth0 promisc # 设置网卡eth0为混杂模式
ifconfig eth0 -promisc # 取消网卡eth0的混杂模式

网络中数据包的分类

  • 广播包:指IP子网内广播的数据包。适用范围较小只在本地子网有效。通过路由器和网络设备控制传输。
  • 单播包:发送者和每一接受者中点对点的网络连接。
  • 组播包:借助组播路由协议建立树形路由,在尽可能远的分岔路口才开始复制和奋发。(224.0.0.0~224.0.0.255是预留的组播地址)

数据包接收流程

  • 网卡收到数据包,获取数据包中的目的MAC地址。
  • 根据网卡驱动设置的网卡接受模式去判断是否接受该数据。
  • 若接受该数据:发出中断信号通知CPU;CPU收到中断信号后根据发出该中断信号的网卡驱动程序的网卡驱动程序地址调用网卡驱动程序;网卡驱动程序处理数据;驱动程序将数据放入信号堆栈;系统接触到数据。
  • 若不接受该数据:网卡直接丢弃该数据;系统不会接触到数据。

安装

1
2
3
4
5
6
# 解锁
# 如果不解锁,可能造成错误:Couldn't find user 'tcpdump'
chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow

# 安装
yum install tcpdump

tcpdump命令格式

1
2
tcpdump [ -DenNqvX ] [ -c count ] [ -F file ] [ -i interface ] [ -r file ]
[ -s snaplen ] [ -w file ] [ expression ]
  • -a 尝试将网络和广播地址转换成名称。
  • -c<数据包数目> 收到指定的数据包数目后,就停止进行倾倒操作。
  • -d 把编译过的数据包编码转换成可阅读的格式,并倾倒到标准输出。
  • -dd 把编译过的数据包编码转换成C语言的格式,并倾倒到标准输出。
  • -ddd 把编译过的数据包编码转换成十进制数字的格式,并倾倒到标准输出。
  • -e 在每列倾倒资料上显示连接层级的文件头。
  • -f 用数字显示网际网络地址。
  • -F<表达文件> 指定内含表达方式的文件。
  • -i<网络界面> 使用指定的网络截面送出数据包。
  • -l 使用标准输出列的缓冲区。
  • -n 不把主机的网络地址转换成名字。
  • -N 不列出域名。
  • -O 不将数据包编码最佳化。
  • -p 不让网络界面进入混杂模式。
  • -q 快速输出,仅列出少数的传输协议信息。
  • -r<数据包文件> 从指定的文件读取数据包数据。
  • -s<数据包大小> 设置每个数据包的大小。
  • -S 用绝对而非相对数值列出TCP关联数。
  • -t 在每列倾倒资料上不显示时间戳记。
  • -tt 在每列倾倒资料上显示未经格式化的时间戳记。
  • -T<数据包类型> 强制将表达方式所指定的数据包转译成设置的数据包类型。
  • -v 详细显示指令执行过程。
  • -vv 更详细显示指令执行过程。
  • -vvv:产生比-vv更详细的输出。
  • -x 用十六进制字码列出数据包资料。
  • -w<数据包文件> 把数据包数据写入指定的文件。

常用实例

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
# 监听特定主机
tcpdump host 182.254.38.55

# 特定来源
tcpdump src host hostname

# 特定目标地址
tcpdump dst host hostname

# 特定端口
tcpdump port 3000

# 监听TCP/UDP
tcpdump tcp

# 来源主机+端口+TCP
# 监听来自主机 10.207.22.254 在端口 8011 上的TCP数据包
tcpdump tcp port 8011 and src host 10.207.22.254

# 监听特定主机之间的通信
tcpdump ip host 210.27.48.1 and 210.27.48.2

# 保存到本地
# 备注:tcpdump 默认会将输出写到缓冲区,只有缓冲区内容达到一定的大小,或者tcpdump退出时,才会将输出写到本地磁盘
tcpdump -n -vvv -c 1000 -w /ldjc/data.pcap

输出

TCP协议行的典型格式如下:

[Timestamp] [Protocol] [Src IP].[Src Port] > [Dst IP].[Dst Port]: [Flags], [Seq], [Ack], [Win Size], [Options], [Data Length]

让我们逐个字段进行说明,并解释以下内容:

1
2
21:53:20.460144 IP 192.168.182.166.57494 > 35.222.85.5.80: Flags [P.], seq 1:88, ack 1, win 29200,  
options [nop,nop,TS val 1067794587 ecr 2600218930], length 87
1
2
3
4
5
21:53:20.460144 - 捕获的数据包的时间戳为本地时间,并使用以下格式:hours:minutes:seconds.frac,
其中frac是自午夜以来的几分之一秒。
IP - 分组协议。 在这种情况下,IP表示Internet协议版本4(IPv4)。
192.168.182.166.57494 - 源IP地址和端口,以点(.)分隔。
35.222.85.5.80 - 目的IP地址和端口,以点号(.)分隔。

TCP 标志字段。 在此示例中,[P.] 表示推送确认数据包,用于确认前一个数据包并发送数据。 其他典型标志字段值如下:

1
2
3
4
5
6
[.] - ACK (Acknowledgment)
[S] - SYN (Start Connection)
[P] - PSH (Push Data)
[F] - FIN (Finish Connection)
[R] - RST (Reset Connection)
[S.] - SYN-ACK (SynAcK Packet)
1
2
3
4
5
6
7
8
9
seq 1:88 - 序列号在first:last表示法中。 它显示了数据包中包含的数据数量。 
除了数据流中的第一个数据包(其中这些数字是绝对的)以外,所有后续数据包均用作相对字节位置。
在此示例中,数字为1:88,表示此数据包包含数据流的字节1至88。 使用-S选项可打印绝对序列号。
ack 1 - 确认号(acknowledgment number)是此连接另一端所期望的下一个数据的序列号。
win 29200 - 窗口号是接收缓冲区中可用字节的数目。
options [nop,nop,TS val 1067794587 ecr 2600218930] - TCP选项。
使用 nop 或 “ no operation” 填充使TCP报头为4字节的倍数。
TS val 是TCP时间戳,而 ecr 表示回显应答。 请访问 IANA 文档以获取有关 TCP 选项的更多信息。
length 87 - 有效载荷数据的长度

参考:

tcpdump抓包wireshark分析

一文搞定tcpdump基本用法

Linux下抓包命令tcpdump详解

Linux基础:用tcpdump抓包

聊聊 tcpdump 与 Wireshark 抓包分析

查看物理CPU的个数

1
cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l

查看物理CPU内核的个数

1
cat /proc/cpuinfo | grep "cpu cores" | uniq

查看所有逻辑CPU的个数

1
cat /proc/cpuinfo | grep "processor" | wc -l

查看每个物理CPU中逻辑CPU的个数

1
cat /proc/cpuinfo | grep 'siblings' | uniq

查询CPU是否启用超线程

1
cat /proc/cpuinfo | grep -e "cpu cores" -e "siblings" | sort | uniq

如果cpu cores数量是siblings数量一半,说明启动了超线程。
如果cpu cores数量和siblings数量一致,则没有启用超线程。

查看CPU的主频

1
cat /proc/cpuinfo |grep MHz|uniq 

查看CPU信息(型号)

1
cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c

查看内存信息

1
cat /proc/meminfo

查看机器型号

1
dmidecode | grep "Product Name"  

CPU运行位数

1
getconf LONG_BIT

线程组

微信截图_20210106142353.png

线程组参数详解:

  • 线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里也就是设置多少个线程数。
  • Ramp-Up Period(in seconds)准备时长:设置的虚拟用户数需要多长时间全部启动。如果线程数为10,准备时长为2,那么需要2秒钟启动10个线程,也就是每秒钟启动5个线程。
  • 循环次数:每个线程发送请求的次数。如果线程数为10,循环次数为100,那么每个线程发送100次请求。总请求数为10*100=1000 。如果勾选了“永远”,那么所有线程会一直发送请求,一到选择停止运行脚本。
  • Delay Thread creation until needed:直到需要时延迟线程的创建。
  • 调度器:设置线程组启动的开始时间和结束时间(配置调度器时,需要勾选循环次数为永远)
    持续时间(秒):测试持续时间,会覆盖结束时间
    启动延迟(秒):测试延迟启动时间,会覆盖启动时间

聚合报告参数详解

  • Label:每个 JMeter 的 element(例如 HTTP Request)都有一个 Name 属性,这里显示的就是 Name 属性的值
  • #Samples:请求数——表示这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100
  • Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,以Transaction 为单位显示平均响应时间
  • Median:中位数,也就是 50% 用户的响应时间
  • 90% Line:90% 用户的响应时间
  • Min:最小响应时间
  • Max:最大响应时间
  • Error%:错误率——错误请求数/请求总数
  • Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数
  • KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec

参考:

JMeter性能测试,完整入门篇

算术运算符

运算符 描述 实例
+ 加 - 两个对象相加 a + b
- 减 - 得到负数,或是一个数减去另一个数 a - b
* 乘 - 两个数相乘,或是返回一个被重复若干次的字符串 a * b
/ 除 - x 除以 y a / b
% 取模 - 返回除法的余数 a % b
** 幂 - 返回x的y次幂 a ** b
// 取整除 - 向下取接近商的整数 >>> 9//2 4 >>> -9//2 -5

比较运算符

1
2
3
4
5
6
== :等于 
!= :不等于
> :大于
< :小于
>= :大于等于
<= :小于等于

赋值运算符

运算符 描述 实例
= 简单的赋值运算符 c = a + b 将 a + b 的运算结果赋值为 c
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
**= 幂赋值运算符 c **= a 等效于 c = c ** a
//= 取整除赋值运算符 c //= a 等效于 c = c // a
1
2
3
4
5
6
# 海象运算符,可在表达式内部为变量赋值。Python3.8 新增。
:=

# 示例中,赋值表达式可以避免调用 len() 两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")

逻辑运算符

1
2
3
and
or
not

成员运算符

1
2
in:如果在指定的序列中找到值返回 True,否则返回 False
not in:如果在指定的序列中没有找到值返回 True,否则返回 False

身份运算符

1
2
isis 是判断两个标识符是不是引用自一个对象
is notis not 是判断两个标识符是不是引用自不同对象

is 与 == 区别:
is 用于判断两个变量引用对象是否为同一个, == 用于判断引用变量的值是否相等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a = 20
b = 20

if ( a is b ):
print ("1 - a 和 b 有相同的标识")
else:
print ("1 - a 和 b 没有相同的标识")

if ( id(a) == id(b) ):
print ("2 - a 和 b 有相同的标识")
else:
print ("2 - a 和 b 没有相同的标识")

# 修改变量 b 的值
b = 30
if ( a is b ):
print ("3 - a 和 b 有相同的标识")
else:
print ("3 - a 和 b 没有相同的标识")

if ( a is not b ):
print ("4 - a 和 b 没有相同的标识")
else:
print ("4 - a 和 b 有相同的标识")

Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。

1
2
var1 = 1
var2 = 'a'

在 Python 中,所说的”类型”是变量所指的内存中对象的类型。变量可以通过赋值指向不同类型的对象。

可以使用 del 语句删除一些对象引用。

del语句的语法是:

1
del var1[,var2[,var3[....,varN]]]

可以通过使用del语句删除单个或多个对象:

1
2
del var
del var_a, var_b

变量赋值

等号(=)用来给变量赋值。

等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值。

1
2
3
counter = 100           # 整型变量
miles = 1000.0 # 浮点型变量
name= "Hello, Python!" # 字符串

1,同时为多个变量赋值。例如:

创建一个整型对象,值为 1,从后向前赋值,三个变量被赋予相同的数值。

1
a = b = c = 1

2,为多个对象指定多个变量。例如:

两个整型对象 1 和 2 的分配给变量 a 和 b,字符串对象 “Python” 分配给变量 c。

1
a, b, c = 1, 2, "Python"

标准数据类型

Python3 中有六个标准的数据类型:

  • Number(数字)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Set(集合)
  • Dictionary(字典)

标准数据类型中:

不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

string、list 和 tuple 都属于 sequence(序列)。

空值用 None 表示

type()和isinstance()函数

isinstance 和 type :

  • type():不会认为子类是一种父类类型。
  • isinstance():会认为子类是一种父类类型。

内置函数 type() 可以用来查询变量所指的对象类型。

1
2
3
>>> a,b,c,d=20,5.5,True,5+4j
>>> print(type(a), type(b), type(c), type(d))
<class 'int'> <class 'float'> <class 'bool'> <class 'complex'>

isinstance

1
2
3
>>> a=1234
>>> isinstance(a,int)
True

数字(Number)类型

Python3 中数字有四种类型:int(整数)、bool(布尔型)、float(浮点数)、complex(复数)。

  • int (整数), 可以为任意大小、包含负数,如 1, 只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
    整型有四种进制表示,分别为:二进制、八进制、十进制、十六进制,说明如下表所示:

    种类 描述 引导符
    二进制 由 0 和 1 组成 0b 或 0B
    八进制 由 0 到 7 组成 0o 或 0O
    十进制 默认情况
    十六进制 由 0 到 9、a 到 f、A 到 F 组成,不区分大小写 0x 或 0X
  • bool (布尔), 如 True。

  • float (浮点数), 由整数部分和小数部分组成,如 1.23、3E-2

  • complex (复数), 由实数部分和虚数部分组成,如 1 + 2j、 1.1 + 2.2j

注意:混合计算时,Python 会把整型转换成为浮点数。

复数由实数部分和虚数部分构成,可以用a + bj,或者 complex(a,b) 表示, 复数的实部a和虚部b都是浮点型

String(字符串)

字符串用单引号 ‘ 或双引号 “ 括起来,同时使用反斜杠 \ 转义特殊字符。Python 没有单独的字符类型,一个字符就是长度为1的字符串。Python 字符串不能被改变。向一个索引位置赋值,比如 word[0] = ‘m’ 会导致错误。

字符串的截取:索引值以 0 为开始值,-1 为从末尾的开始位置。

遵循左闭右开原则,str[0:2] 是不包含第 3 个字符的,即不包括尾标。

1
变量[头下标:尾下标]

实例:

1
2
3
4
5
6
7
8
9
str = 'Hello, Python!'

print (str) # 输出字符串
print (str[0:-1]) # 输出第一个到倒数第二个的所有字符
print (str[0]) # 输出字符串第一个字符
print (str[2:5]) # 输出从第三个开始到第五个的字符
print (str[2:]) # 输出从第三个开始的后的所有字符
print (str * 2) # 输出字符串两次,也可以写成 print (2 * str)
print (str + "TEST") # 连接字符串

加号 + 是列表连接运算符,星号 * 是重复操作。

反斜杠 \ 转义特殊字符,如果你不想让反斜杠发生转义,可以在字符串前面添加一个 r (raw),表示原始字符串

1
2
3
4
5
6
print('RHello, \nPython!')
RHello,
Python!

print(r'Hello, \nPython!')
Hello, \nPython!
  • ord() 函数返回单个字符的编码;
  • chr() 函数把编码转成相应字符;
1
2
3
4
5
6
s = 'A'
print(ord(s))
print(chr(65))

65
A

python三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符

1
2
3
4
5
6
para_str = """这是一个多行字符串的实例
多行字符串可以使用制表符
TAB ( \t )。
也可以使用换行符 [ \n ]。
"""
print (para_str)

格式化

Python 使用 % 格式化字符串,常用占位符如下表所示:

占位符 描述
%s 格式化字符串
%d 格式化整数
%f 格式化浮点数

实例:

1
2
3
4
print('Hello %s' % 'Python')
Hello Python

print ("我叫 %s 今年 %d 岁!" % ('小明', 20))

format() 方法格式化:

1
print('{0} {1}'.format('Hello', 'Python'))

f-string

f-string 是 python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。

1
2
name = 'Python'
f'Hello {name}' # 替换变量

List(列表)

列表是写在方括号 [] 之间、用逗号分隔开的元素列表。List中的元素是可以改变的。列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表(所谓嵌套)。和字符串一样,列表同样可以被索引和截取,列表被截取后返回一个包含所需元素的新列表。

列表截取的语法:索引值以 0 为开始值,-1 为从末尾的开始位置。

1
变量[头下标:尾下标]

加号 + 是列表连接运算符,星号 * 是重复操作。

  • 更新

append() 向列表中添加新元素

1
2
3
4
5
6
7
8
9
10
l = ['Hello', 'Python',1]

# 修改列表中第3个元素
l[1] = 2

# 向列表中添加新元素
l.append('Hello')

print('l[2] -->', l[1])
print('l -->', l)

输出:

1
2
l[2] --> 2
l --> ['Hello', 'Python', 2, '666']
  • 删除

del 删除列表中元素

1
2
3
l = ['Hello', 'Python',1]
# 删除列表中第二个元素
del l[1]
  • count():统计列表中某个元素出现的次数
  • index():查找某个元素在列表中首次出现的位置(即索引)
  • remove():移除列表中某个值的首次匹配项
  • sort():对列表中元素进行排序
  • copy():复制列表
1
2
3
4
5
6
l = ['d', 'b', 'a', 'f', 'd']
print("l.count('d') -->", l.count('d'))
print("l.index('d') -->", l.index('d'))
l.remove('d')
l.sort()
lc = l.copy()

Tuple(元组)

元组(tuple)与列表类似,不同之处在于元组的元素不能修改,常用于保存不可修改的内容。元组写在小括号 () 里,元素之间用逗号隔开,元组中的元素类型也可以不相同,元组也可以使用+操作符进行拼接。

常用方法

  • len():计算元组中元素个数
  • max():返回元组中元素最大值
  • min():返回元组中元素最小值
  • tuple():将列表转换为元组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tup1 = ()    # 空元组
tup2 = (20,) # 一个元素,需要在元素后添加逗号
tinytuple = (123, 'Python')
print (tinytuple * 2) # 输出两次元组
print (tuple + tinytuple) # 连接元组

t = ('Hello','Python','666')
t = ('Hello','Python','666','777')

del t
print('len(t) -->', len(t))
print('max(t) -->', max(t))
print('min(t) -->', min(t))

l = ['d', 'b', 'a', 'f', 'd']
t = tuple(l)

Set(集合)

集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员。

基本功能是进行成员关系测试和删除重复元素。

可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
s = {'a', 'b', 'c'}

# 或者
set(['a', 'b', 'c'])

# 添加元素可以使用 add 或 update 方法,如果元素已经存在,则不进行操作
s.update('e')
s.add('a')

# 删除元素
s.remove('c')

# 获取集合的长度
len(s)

# 清空集合
s.clear()

Dictionary(字典)

字典的内容在花括号 {} 内,键-值(key-value)之间用冒号 : 分隔,键值对之间用逗号 , 分隔。

键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变的,如字符串,数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建字典
d = {'name':'富贵', 'age':'28',2:'num'}

# 使用 dict 函数
# 方式一
l = [('name', '开花'), ('age', 29)]
d = dict(l)
# 方式二
d = dict(name='金尚', age='18')

# 方式三
dict = {}
dict['one'] = "1 - 开花"
dict[2] = "2 - 开花"

# 空字典
d = dict()
d = {}

print (dict['name']) # 输出键为 'name' 的值
print (dict[2]) # 输出键为 2 的值
print (d) # 输出完整的字典
print (d.keys()) # 输出所有键
print (d.values()) # 输出所有值

集合与字典

  • 无序:集合是无序的,所以不支持索引;字典同样也是无序的,但由于其元素是由键(key)和值(value)两个属性组成的键值对,可以通过键(key)来进行索引
  • 元素唯一性:集合是无重复元素的序列,会自动去除重复元素;字典因为其key唯一性,所以也不会出现相同元素

编码

Python2 中默认编码为 ASCII,内容如果为汉字,不指定编码则会乱码,想要指定编码为 UTF-8,Python 中通过在开头加入:

1
# -*- coding: UTF-8 -*-

Python3 中默认编码为 UTF-8,因此在使用 Python3 时,通常不需指定编码。

标识符

标识符是用于给变量、函数、语句块等命名,Python 中标识符由字母、数字、下划线组成,第一个字符必须是字母表中字母或下划线 _,不能以数字开头,区分大小写。

在 Python 3 中,可以用中文作为变量名,非 ASCII 标识符也是允许的了。

以下划线开头的标识符的特殊含义:

  • 单下划线开头的标识符,如:_xxx ,表示不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx import * 导入;
  • 双下划线开头的标识符,如:__xx,表示私有成员;
  • 双下划线开头和结尾的标识符,如:xx__,表示 Python 中内置标识,如:__init() 表示类的构造函数。

关键字

1
2
3
>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', '__peg_parser__', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

注释

  • 单行注释以 # 开头。
  • 多行注释可以用多个 # 号,三个单引号(’’’)或三个双引号(”””)。
1
2
3
4
5
6
7
8
9
10
11
12
# 第一个注释
# 第二个注释

'''
第三注释
第四注释
'''

"""
第五注释
第六注释
"""

行与缩进

Python 使用缩进来表示代码块,控制类、函数、逻辑判断等,,不需要使用大括号 {} ,缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数,如果语句缩进数的空格数不一致,会导致运行错误。

1
2
3
4
if True:
print ("True")
else:
print ("False")

多行语句

如果Python 的语句很长,可以使用反斜杠 (\) 来实现多行语句,例如:

1
2
3
total = one + \
two + \
three

如果包含在 []、{}、() 括号中,则不需要使用反斜杠 (\)。如下所示:

1
2
total = ['item_one', 'item_two', 'item_three',
'item_four', 'item_five']

Python3学习-基础语法
Python3学习-基本数据类型
Python3学习-运算符
Python3学习-基本语句
Python3学习-函数
Python3学习-迭代器与生成器
Python3学习-数据结构
Python3学习-模块与包
Python3学习-输入和输出
Python3-字符串格式化
Python3学习-文件操作
Python3学习-OS模块
Python3学习-错误和异常处理
Python3学习-面向对象
Python3学习-命名空间和作用域
Python3学习-函数装饰器
Python3-星号和双星号变量用法
Python3-时间模块
Python3-数学模块
Python3-多线程
Python3-多进程
Python3-MySQL操作
Python3-操作SqLite
Python3-JSON操作
Python3-XML操作
Python3-Word操作
Python3-Excel操作
Python3-网络编程
Python3-标准库1

密码更换周期设置

密码定期更换配置在 /etc/login.defs 中:

1
2
3
4
PASS_MAX_DAYS	90   # 密码到期时间
PASS_MIN_DAYS 6 # 初始密码更改时间
PASS_MIN_LEN 8 # 密码最小长度
PASS_WARN_AGE 10 # 密码过期提示时间

注意:

/etc/login.defs 中设置仅影响创建用户,而不会影响现有用户。
如果设置为现有用户,使用命令 chage -M(days)(user),例如:chage -M 60 root

chage命令

chage 命令是用来修改帐号和密码的有效期限。

语法

chage [选项] 用户名

选项

  • -m:密码可更改的最小天数。为零时代表任何时候都可以更改密码。
  • -M:密码保持有效的最大天数。
  • -w:用户密码到期前,提前收到警告信息的天数。
  • -E:帐号到期的日期。过了这天,此帐号将不可用。
  • -d:上一次更改的日期。
  • -i:停滞时期。如果一个密码已过期这些天,那么此帐号将不可用。
  • -l:例出当前的设置。由非特权用户来确定他们的密码或帐号何时过期。

示例

1
2
3
4
5
# 查看root配置
chage -l root

# 设置root密码90天过期
chage -M 90 root

密码复杂度设置

CentOS7/RHEL7 开始使用 pam_pwquality 模块进行密码复杂度策略的控制管理。pam_pwquality 替换了原来 Centos6/RHEL6 中的 pam_cracklib 模块,并向后兼容。

pam_pwquality模块设置

retry=N 允许重试N次
difok=N 新密码必需与旧密码不同的位数 difok=3 新密码必须与旧密码有3位不同
minlen=N 最小位数
ucredit=N 大写字母位数
lcredit=N 小写字母位数
dcredit=N 数字个数
ocredit=N 特殊字母的个数

两种方式实现:

  • 1,直接指定 pam_pwquality 模块参数,在 /etc/pam.d/system-auth 中的 password requisite pam_pwquality.so 行尾添加具体参数,比如 minlen=16 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1 ,表示最小密码长度16位,数字,大小写字母,特殊字符均至少包含1位。

N >= 0:密码中最多有多少个;
N < 0 :密码中最少有多少个;

1
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1
  • 2,通过修改 /etc/security/pwquality.conf 参数文件,定义密码复杂度规则。

修改 pwquality.conf 参数文件有2种方法。

(1)直接修改 /etc/security/pwquality.conf
(2)使用 authconfig 命令修改,修改后最终会体现在 /etc/security/pwquality.conf

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
29
30
31
32
33
34
35
36
37
38
39
40
# 最小长度
authconfig --passminlen=8 --update
grep "^minlen" /etc/security/pwquality.conf

# 设置同一类的允许连续字符的最大数目
authconfig --passmaxclassrepeat=6 --update
grep "^maxclassrepeat" /etc/security/pwquality.conf

# 至少需要一个小写字符
authconfig --enablereqlower --update
grep "^lcredit" /etc/security/pwquality.conf

# 至少需要一个大写字符
authconfig --enablerequpper --update
grep "^ucredit" /etc/security/pwquality.conf

# 至少需要一个数字
authconfig --enablereqdigit --update
grep "^dcredit" /etc/security/pwquality.conf

# 至少一个特殊字符
authconfig --enablereqother --update
grep "^ocredit" /etc/security/pwquality.conf

# 以下需要单独设置
vim /etc/security/pwquality.conf

# 添加一下配置

# 设置单调字符序列的最大长度
maxsequence = 5

# 新密码中不能出现在旧密码中的字符数
difok = 5

# 检查来自用户 passwd 条目的 GECOS 字段的长度超过3个字符的字是否包含在新密码中。
gecoscheck = 1

# 设置不能包含在密码中的Ssace分隔的单词列表
badwords = test test1 test2

示例:

1
2
vim /etc/security/pwquality.conf
grep -vE "^#|^$" /etc/security/pwquality.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
minlen = 8

# 新密码所需的字符类(数字、大写、小写、其他)的最小字符数。
minclass = 1

# 新密码中允许的连续相同字符的最大数量。如果值为 0,则禁用检查。
maxrepeat = 0

maxclassrepeat = 6
lcredit = -1
ucredit = -1
dcredit = -1
ocredit = -1

Centos7 继续使用 pam_cracklib 模块检验密码复杂度

vim /etc/pam.d/system-auth

1
2
# 添加到 pam_pwquality.so 所在行的上行
password requisite pam_cracklib.so try_first_pass retry=3 type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1

Read Hat配置密码复杂度

vim /etc/pam.d/system-auth

1
password   requisite      pam_cracklib.so retry=3 difok=3 minlen=8 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1

参考:

CentOS7上密码复杂度设置

CentOS7密码复杂度配置

chage命令

CentOS 7 设置密码规则

数据库审计简介

数据库审计(简称 DBAudit)能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。数据库审计可以记录某用户在某个时间点对数据库的操作,包括登录、连接、对表的增删改查等等,便于责任追溯,问题查找,当然开启审计功能在一定方面会影响数据库性能。

环境

  • 操作系统:CentOS7.4
  • Mysql:mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz (社区版)
  • Mariadb:mariadb-10.5.8-linux-x86_64

由于MySQL的社区版不支持审计系统,可通过第三方插件实现,此次采用MariaDB的server_audit插件来记录{时间,节点,用户,源IP,事件类型,库,语句,影响行数},注:从mysql8开始已不支持该插件。

安装插件

1,登陆 Mysql,查看插件安装目录:

1
2
3
4
5
6
7
mysql> show global variables like 'plugin_dir';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1 row in set (0.01 sec)

2,提取 Mariadb 审计插件,并放置Mysql插件目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 拷贝
cp /ldjc/mariadb-10.5.8-linux-x86_64/lib/plugin/server_audit.so /usr/local/mysql/lib/plugin/

# 授予执行权限
chmod +x /usr/local/mysql/lib/plugin/server_audit.so

# 安装
# 或者 在 my.cnf 中配置:plugin_load=server_audit=server_audit.so
install plugin server_audit soname 'server_audit.so';

# 备注:
# UNINSTALL PLUGIN server_audit; # 卸载插件
# show variables like '%audit%';

# 查看插件
show plugins;

3,新建 auditlogs 目录,并更改所属的组和用户

1
2
3
mkdir /usr/local/mysql/auditlogs
chown -R mysql /usr/local/mysql/auditlogs
chgrp -R mysql /usr/local/mysql/auditlogs

4,修改my.cnf配置文件

vim /usr/local/mysql/my.cnf

在 [mysqld] 标签下添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#防止server_audit 插件被卸载 进行配置文件配置
server_audit=FORCE_PLUS_PERMANENT

#指定哪些操作被记录到日志文件中
server_audit_events='CONNECT,QUERY,TABLE,QUERY_DDL'

#开启审计功能
server_audit_logging=on

#默认存放路径,可以不写,默认到data文件下
server_audit_file_path=/usr/local/mysql/auditlogs

#设置文件大小 默认1000000,1073741824=1GB
server_audit_file_rotate_size=1073741824

#指定日志文件的数量,如果为0日志将从不轮转
server_audit_file_rotations=200

#强制日志文件轮转
server_audit_file_rotate_now=ON

4,重启mysql

1
2
3
4
/etc/init.d/mysqld restart

# 或
service mysqld restart

验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> show variables like '%audit%';
+-------------------------------+-------------------------------+
| Variable_name | Value |
+-------------------------------+-------------------------------+
| server_audit_events | CONNECT,QUERY,TABLE,QUERY_DDL |
| server_audit_excl_users | |
| server_audit_file_path | /usr/local/mysql/auditlogs |
| server_audit_file_rotate_now | ON |
| server_audit_file_rotate_size | 1073741824 |
| server_audit_file_rotations | 200 |
| server_audit_incl_users | |
| server_audit_loc_info | |
| server_audit_logging | ON |
| server_audit_mode | 1 |
| server_audit_output_type | file |
| server_audit_query_log_limit | 1024 |
| server_audit_syslog_facility | LOG_USER |
| server_audit_syslog_ident | mysql-server_auditing |
| server_audit_syslog_info | |
| server_audit_syslog_priority | LOG_INFO |
+-------------------------------+-------------------------------+
16 rows in set (0.00 sec)
1
cat /usr/local/mysql/auditlogs/server_audit.log

参数配置说明

  • server_audit:启用安全审计插件;
  • server_audit_output_type:指定日志输出类型,可为 SYSLOG或 FILE
  • server_audit_logging:启动或关闭审计
  • server_audit_events:指定记录事件的类型,可以用逗号分隔的多个值(connect,query,table),如果开启了查询缓存(query cache),查询直接从查询缓存返回数据,将没有 table 记录
  • server_audit_file_path:如 server_audit_output_type 为 FILE,使用该变量设置存储日志的文件,可以指定目录,默认存放在数据目录的 server_audit.log 文件中
  • server_audit_file_rotate_size:限制日志文件的大小
  • server_audit_file_rotations:指定日志文件的数量,如果为0日志将从不轮转
  • server_audit_file_rotate_now:强制日志文件轮转
  • server_audit_incl_users:指定哪些用户的活动将记录,connect将不受此变量影响,该变量比server_audit_excl_users优先级高
  • server_audit_syslog_facility:默认为LOG_USER,指定facility
  • server_audit_syslog_ident:设置ident,作为每个syslog记录的一部分
  • server_audit_syslog_info:指定的info字符串将添加到syslog记录
  • server_audit_syslog_priority:定义记录日志的syslogd priority
  • server_audit_excl_users:该列表的用户行为将不记录,connect将不受该设置影响
  • server_audit_mode:标识版本,用于开发测试

参考:

MariaDB Audit Plugin Options and System Variables

Mysql5.7安装server_audit审计

MySQL5.7审计功能windows系统

MySQL数据库启用安全审计功能