Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

14.3. 技术岗怎样做工作交接

在国内工作交接如同家常便饭,有数据显示员工服务于公司的平均时间,其中80后平均是3年时间,90后平均为2~2.5,95后约半年~1.5年。如此频繁地更换工作不仅仅是员工自身问题,公司用人单位也存在一定问题,这里就不讨论了。

在早期管理学还未在中国普及的时候,50/60/70后沿用了自古以来的老旧的管理思想,搞仁制和驭人术那套,如今已经是2022年了,管理学已经非常成熟,大学有专门管理课,社会上有专业的管理培训,但仍有大量公司在采用中式管理,且管理层搞得不亦乐乎,并未有改变的想法。

国内公司存在的问题:

所以在工作中,工作交接是不可避免的,无论是用人单位找到你,还是你主动应聘岗位,工作交接都是一项极具挑战的工作,俗称“擦屁股”,我们怎样做好工作交接呢?

14.3.1. 工作交接过程

任何工作交接都会丢失80%内容,交接者只能接受20%的工作内容。

丢失的内容有可能是交接者没有想到,交接者故意隐瞒,交接者故意挖坑,交接者说了但是接受者没听懂或忘记了,总之工作不可能达到 100% 的交接。

尤其是国内企业和雇员紧张的劳动关系,几乎大部分的工作交接都不太顺利。

同时离职员工去下家公司也同样面临严峻挑战的工作交接过程,似乎这是一个无解的死循环。

即使是我们口中常说的大厂也存在上述问题。

工作交接过程中可能遇到的问题:

  • 没有足够的书面资料
  • 口头只给你说一次
  • 交接者故意隐瞒信息
  • 交接者故意给你挖坑
  • 交接者不主动、敷衍、不配合
  • 没有给你足够的时间学习、理解、吸收
  • 你不问,对方不会主动给你讲

你能做的是尽量获得更多交接文档,很多事你要先想到,主动问对方,交接者没有责任和义务帮你,他想尽快甩锅走人,你只能求菩萨保佑他跟用人单位没有纠纷。

这导致很多时候工作交接要靠我们自己,同时我们离职的时候也会用这些办法对付接收我们工作的人,呵呵!!!

14.3.2. 确认入口

以技术工作交接为例,如何快速摸清系统,掌握各系统模块之间的关系呢?

互联网入口都有哪些:

  • 网站入口
  • 手机App入口
  • 小程序/公众号/第三方入口
  • TCP/UDP Socket 入口
域名检查

使用 nslookup/dig 等工具检查域名

  • A 记录,主机解析
  • MX 记录,邮件交换记录
  • TXT 记录,一些特定服务
  • AAAA 记录,IPv6 主机解析
  • NS 记录

然后在登陆的DNS管理界面查漏补缺,这里重点是 MX 记录,很多时候会忽略,导致邮件服务不能用。

IP地址检查

网站入口通常是域名或IP地址,例如我的域名是 www.netkiller.cn,使用 ping 工具查看其IP地址

		
[root@netkiller ~]# ping www.netkiller.cn		
		
			

手机App链接的API地址需要抓包工具

14.3.3. 网络设备

备份配置文件

登陆网络设备,备份配置文件,然后分析网络拓扑,如果有交接文档,就按照文档核对 vlan和每个路由器和交换机端口功能。

Cisco 网络设备使用 show running-config 查看配置文件

		
Router#show running-config
Router#show startup-config
		
			

H3C 网络设备使用 display current-configuration 查看配置文件

		
[WA2220E-AG]display current-configuration
#
 version 5.20, Release 1110P01
#
 sysname WA2220E-AG
#
 domain default enable system
#
 telnet server enable
#
 port-security enable
#
vlan 1
#
radius scheme system
#
domain system
 access-limit disable
 state active
 idle-cut disable
 self-service-url disable		
		
			

Juniper 网络设备,使用 get config 查看配置文件

		
[root@netkiller ~]# ssh neo@192.168.1.1
neo@192.168.3.1's password:
Remote Management Console
firewall-> get config
Total Config size 17376:
set clock ntp
set clock timezone 7
set vrouter trust-vr sharable
set vrouter "untrust-vr"
exit
set vrouter "trust-vr"
unset auto-route-export
exit
...
...
...
exit
set vrouter "untrust-vr"
exit
set vrouter "trust-vr"
exit
firewall->		
		
			

这些网络设备如何使用,请参考《Netkiller Network 手札》

绘制网络拓扑图

几乎90%(可以我说少了)公司,在IT这块的管理十分混乱,走进机房,网线乱如麻,你根本不知道那根网线链接了什么设备,我们需要先理清重点设备的链接拓扑图。

这里以 H3C 为例,其他设备操作方式大同小异,下面是找到接口对等设备的IP地址

			
<H3C>display arp interface GE1/0/32
  Type: S-Static   D-Dynamic   O-Openflow   R-Rule   M-Multiport  I-Invalid
IP address      MAC address    VLAN/VSI name Interface                Aging Type
172.16.200.75   b07b-2523-5326 200           GE1/0/32                 501   D   		
			
			

通过 mac 地址找接口

			
<H3C>display arp all | include 6227-d242-269e
172.16.0.68     6227-d242-269e 10            GE1/0/3                  1085  D 			
			
			

通过 ip 地址找接口

			
<H3C>display arp all | include 172.16.200.102
172.16.200.102  001e-67fa-df92 200           GE1/0/36                 282   D  			
			
			

14.3.4. 服务器系统检查

当我们知道服务器IP地址之后就可以登录服务器了

		
[root@netkiller ~]# ssh root@www.netkiller.cn
		
		

登陆服务器之后首先快速检查是否有安全问题

检查用户权限
			
[root@netkiller ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
unbound:x:997:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
libstoragemgmt:x:996:992:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
setroubleshoot:x:995:991::/var/lib/setroubleshoot:/sbin/nologin
cockpit-ws:x:994:990:User for cockpit web service:/nonexisting:/sbin/nologin
cockpit-wsinstance:x:993:989:User for cockpit-ws instances:/nonexisting:/sbin/nologin
sssd:x:992:988:User for sssd:/:/sbin/nologin
chrony:x:991:987::/var/lib/chrony:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
docker:x:986:986:Container Administrator:/home/docker:/bin/bash
git:x:1000:1000::/home/git:/bin/bash
caddy:x:985:984:Caddy web server:/var/lib/caddy:/sbin/nologin
nginx:x:984:983:Nginx web server:/var/lib/nginx:/sbin/nologin
			
			

通常除了 root 用户,小于1000的UID的用户 SHELL 应该是 /sbin/nologin

重点检查拥有 shell 权限的用户,非必要全部改为 /sbin/nologin

			
[root@netkiller ~]# cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
docker:x:986:986:Container Administrator:/home/docker:/bin/bash
git:x:1000:1000::/home/git:/bin/bash
			
			

检查用户是否激活,并设置密码

			
[root@netkiller ~]# cat /etc/shadow
root:$6$XyW4o/lZWdu$VsjNYW8nVcE63cWwAxLxBe5s22vt4hQCOivzxo5RQ3rGbcBkfWnc/ATiy073D7/aIHQaDZplIJWz51s4Pzkn0.:19173:0:99999:7:::
bin:*:18505:0:99999:7:::
daemon:*:18505:0:99999:7:::
adm:*:18505:0:99999:7:::
lp:*:18505:0:99999:7:::
sync:*:18505:0:99999:7:::
shutdown:*:18505:0:99999:7:::
halt:*:18505:0:99999:7:::
mail:*:18505:0:99999:7:::
operator:*:18505:0:99999:7:::
games:*:18505:0:99999:7:::
ftp:*:18505:0:99999:7:::
nobody:*:18505:0:99999:7:::
dbus:!!:19136::::::
systemd-coredump:!!:19136::::::
systemd-resolve:!!:19136::::::
tss:!!:19136::::::
polkitd:!!:19136::::::
unbound:!!:19136::::::
libstoragemgmt:!!:19136::::::
setroubleshoot:!!:19136::::::
cockpit-ws:!!:19136::::::
cockpit-wsinstance:!!:19136::::::
sssd:!!:19136::::::
chrony:!!:19136::::::
sshd:!!:19136::::::
tcpdump:!!:19136::::::
nscd:!!:19136::::::
postfix:!!:19136::::::
docker:$6$6.KJvlfezlr7q09N$Xo83rIqChY0sLrvyCGnNYqPpCsREk1h1En7eNwZBV9sjN6XVOO9xgjuKGn..tAhElYK1SLI6mvZa6pxsCcuqb/:19177:0:99999:7:::
git:$6$EcduJ7Z1HAZWhRPN$wyG7OOpQaw84FgvAsXBPUKr.dZWEDIaWhMKeoEuNRvpfzvoeKo4gei028lSCm./nAvFqRpos/2Ng4ARHR5FRj.:19173:0:99999:7:::
caddy:!!:19177::::::
nginx:!!:19192::::::
			
			

!! 和 * 是未设置密码,该用户无法登陆系统,$6$ 表示该用户有密码

这三个用户是有密码的

			
[root@netkiller ~]# cat /etc/shadow | grep '\$6\$'
root:$6$XyW4o/lZWdu$VsjNYW8nVcE63cWwAxLxBe5s22vt4hQCOivzxo5RQ3rGbcBkfWnc/ATiy073D7/aIHQaDZplIJWz51s4Pzkn0.:19173:0:99999:7:::
docker:$6$6.KJvlfezlr7q09N$Xo83rIqChY0sLrvyCGnNYqPpCsREk1h1En7eNwZBV9sjN6XVOO9xgjuKGn..tAhElYK1SLI6mvZa6pxsCcuqb/:19177:0:99999:7:::
git:$6$EcduJ7Z1HAZWhRPN$wyG7OOpQaw84FgvAsXBPUKr.dZWEDIaWhMKeoEuNRvpfzvoeKo4gei028lSCm./nAvFqRpos/2Ng4ARHR5FRj.:19173:0:99999:7:::
			
			
锁定/解锁用户

发现可疑用户,我们可以先把它锁掉,让他登陆不了。使用 passwd -l 给用户加锁,-u 解锁。

			
[root@netkiller ~]# passwd --help
Usage: passwd [OPTION...] <accountName>
  -k, --keep-tokens       keep non-expired authentication tokens
  -d, --delete            delete the password for the named account (root only); also removes password lock if any
  -l, --lock              lock the password for the named account (root only)
  -u, --unlock            unlock the password for the named account (root only)
  -e, --expire            expire the password for the named account (root only)
  -f, --force             force operation
  -x, --maximum=DAYS      maximum password lifetime (root only)
  -n, --minimum=DAYS      minimum password lifetime (root only)
  -w, --warning=DAYS      number of days warning users receives before password expiration (root only)
  -i, --inactive=DAYS     number of days after password expiration when an account becomes disabled (root only)
  -S, --status            report password status on the named account (root only)
      --stdin             read new tokens from stdin (root only)

Help options:
  -?, --help              Show this help message
      --usage             Display brief usage message
			
			

例如我们要禁止 git 用户登陆系统

			
[root@netkiller ~]# passwd -l git
Locking password for user git.
passwd: Success			
			
			

恢复 git 用户登陆权限

			
[root@netkiller ~]# passwd -u git
Unlocking password for user git.
passwd: Success			
			
			

实际的加锁与解锁的过程就是在 shadow 文件中,密码前面增加 !! 符号。

			
[root@netkiller ~]# passwd -l git
Locking password for user git.
passwd: Success	
			
[root@netkiller ~]# cat /etc/shadow | grep 'git'
git:!!$6$EcduJ7Z1HAZWhRPN$wyG7OOpQaw84FgvAsXBPUKr.dZWEDIaWhMKeoEuNRvpfzvoeKo4gei028lSCm./nAvFqRpos/2Ng4ARHR5FRj.:19173:0:99999:7:::

[root@netkiller ~]# passwd -u git
Unlocking password for user git.
passwd: Success

[root@netkiller ~]# cat /etc/shadow | grep 'git'
git:$6$EcduJ7Z1HAZWhRPN$wyG7OOpQaw84FgvAsXBPUKr.dZWEDIaWhMKeoEuNRvpfzvoeKo4gei028lSCm./nAvFqRpos/2Ng4ARHR5FRj.:19173:0:99999:7:::
			
			
检查端口

非法进入服务器必须某种服务端口,我们确认用户安全后,接下来要做的就是扫描端口,看看服务器上开了哪些端口。

			
[root@netkiller ~]# dnf install -y nmap
			
			

nmap 使用方法请看我的《Netkiller Linux 手札》本文只教方法论。

			
[root@netkiller ~]# nmap www.netkiller.cn
Starting Nmap 7.70 ( https://nmap.org ) at 2022-07-23 16:23 CST
Nmap scan report for chat.netkiller.cn (8.219.73.35)
Host is up (0.00041s latency).
Not shown: 993 filtered ports
PORT     STATE  SERVICE
22/tcp   open   ssh
80/tcp   open   http
443/tcp  open   https
3389/tcp closed ms-wbt-server
8000/tcp closed http-alt
8080/tcp closed http-proxy
9000/tcp closed cslistener

Nmap done: 1 IP address (1 host up) scanned in 25.40 seconds			
			
			

通过端口找进程,可以使用 ss 和 netstat 两个工具完成

			
[root@netkiller ~]# netstat -antup|grep 80
tcp        0      0 172.22.119.108:20507    100.103.15.60:80        ESTABLISHED 1490/AliYunDun      
tcp6       0      0 :::80                   :::*                    LISTEN      1629762/caddy       

[root@netkiller ~]# ss -lntp
State                    Recv-Q                   Send-Q                                     Local Address:Port                                     Peer Address:Port                   Process                                               
LISTEN                   0                        128                                              0.0.0.0:22                                            0.0.0.0:*                       users:(("sshd",pid=1189,fd=5))                       
LISTEN                   0                        1024                                           127.0.0.1:2019                                          0.0.0.0:*                       users:(("caddy",pid=1629762,fd=3))                   
LISTEN                   0                        1024                                                   *:80                                                  *:*                       users:(("caddy",pid=1629762,fd=8))                   
LISTEN                   0                        1024                                                   *:443                                                 *:*                       users:(("caddy",pid=1629762,fd=7))  
			
			

这里可以看到 80 端口是 1629762 进程监听的,该进程是 caddy 它是一个 web 服务器

通过进程找进程ID

			
[root@netkiller ~]# pgrep caddy
1629762
			
			

多IP地址骚猫

			
while read ipaddress
do
	echo "----- $ipaddress ----- "
    nmap -p 1-65535 $ipaddress | tail -n +5 | head -n -1
    echo
done << EOF
172.16.0.1
172.18.0.1
192.168.0.1
EOF			
			
			
检查进程

Linux 系统进程带有中括号的是内核进程,除此之外都需要一一排查

			
[root@netkiller ~]# ps ax | grep '\['
      2 ?        S      0:01 [kthreadd]
      3 ?        I<     0:00 [rcu_gp]
      4 ?        I<     0:00 [rcu_par_gp]
      6 ?        I<     0:00 [kworker/0:0H-events_highpri]
      9 ?        I<     0:00 [mm_percpu_wq]
     10 ?        S      0:00 [rcu_tasks_rude_]
     11 ?        S      0:00 [rcu_tasks_trace]
     12 ?        S      0:01 [ksoftirqd/0]
     13 ?        I      9:14 [rcu_sched]
     14 ?        S      0:00 [migration/0]
     15 ?        S      0:00 [watchdog/0]
     16 ?        S      0:00 [cpuhp/0]
     17 ?        S      0:00 [cpuhp/1]
     18 ?        S      0:00 [watchdog/1]
     19 ?        S      0:00 [migration/1]
     20 ?        S      0:00 [ksoftirqd/1]
     22 ?        I<     0:00 [kworker/1:0H-events_highpri]
     23 ?        S      0:00 [cpuhp/2]
     24 ?        S      0:01 [watchdog/2]
     25 ?        S      0:00 [migration/2]
     26 ?        S      0:00 [ksoftirqd/2]
     28 ?        I<     0:00 [kworker/2:0H-events_highpri]
     29 ?        S      0:00 [cpuhp/3]
     30 ?        S      0:01 [watchdog/3]
     31 ?        S      0:00 [migration/3]
     32 ?        S      0:00 [ksoftirqd/3]
     34 ?        I<     0:00 [kworker/3:0H-events_highpri]
     35 ?        S      0:00 [cpuhp/4]
     36 ?        S      0:01 [watchdog/4]
     37 ?        S      0:00 [migration/4]
     38 ?        S      0:00 [ksoftirqd/4]
     40 ?        I<     0:00 [kworker/4:0H-events_highpri]
     41 ?        S      0:00 [cpuhp/5]
     42 ?        S      0:01 [watchdog/5]
     43 ?        S      0:00 [migration/5]
     44 ?        S      0:00 [ksoftirqd/5]
     46 ?        I<     0:00 [kworker/5:0H-events_highpri]
     47 ?        S      0:00 [cpuhp/6]
     48 ?        S      0:01 [watchdog/6]
     49 ?        S      0:00 [migration/6]
     50 ?        S      0:00 [ksoftirqd/6]
     52 ?        I<     0:00 [kworker/6:0H-events_highpri]
     53 ?        S      0:00 [cpuhp/7]
     54 ?        S      0:02 [watchdog/7]
     55 ?        S      0:00 [migration/7]
     56 ?        S      0:00 [ksoftirqd/7]
     58 ?        I<     0:00 [kworker/7:0H-events_highpri]
     67 ?        S      0:00 [kdevtmpfs]
     68 ?        I<     0:00 [netns]
     69 ?        S      0:00 [kauditd]
     70 ?        S      0:01 [khungtaskd]
     71 ?        S      0:00 [oom_reaper]
     72 ?        I<     0:00 [writeback]
     73 ?        S      0:00 [kcompactd0]
     74 ?        SN     0:00 [ksmd]
     75 ?        SN     0:18 [khugepaged]
     76 ?        I<     0:00 [crypto]
     77 ?        I<     0:00 [kintegrityd]
     78 ?        I<     0:00 [kblockd]
     79 ?        I<     0:00 [blkcg_punt_bio]
     80 ?        I<     0:00 [tpm_dev_wq]
     81 ?        I<     0:00 [md]
     82 ?        I<     0:00 [edac-poller]
     83 ?        S      0:00 [watchdogd]
     84 ?        I<     0:01 [kworker/0:1H-kblockd]
    118 ?        S      0:00 [kswapd0]
    224 ?        I<     0:00 [kthrotld]
    225 ?        I<     0:00 [acpi_thermal_pm]
    226 ?        I<     0:00 [kmpath_rdacd]
    227 ?        I<     0:00 [kaluad]
    229 ?        I<     0:02 [kworker/4:1H-kblockd]
    230 ?        I<     0:00 [ipv6_addrconf]
    232 ?        I<     0:00 [kstrp]
    313 ?        I<     0:01 [kworker/5:1H-kblockd]
    319 ?        I<     0:01 [kworker/2:1H-kblockd]
    347 ?        I<     0:14 [kworker/7:1H-xfs-log/vda1]
    350 ?        I<     0:01 [kworker/3:1H-kblockd]
    355 ?        I<     0:01 [kworker/1:1H-kblockd]
    361 ?        I<     0:01 [kworker/6:1H-kblockd]
    501 ?        I<     0:00 [ata_sff]
    502 ?        S      0:00 [scsi_eh_0]
    503 ?        I<     0:00 [scsi_tmf_0]
    504 ?        S      0:00 [scsi_eh_1]
    505 ?        I<     0:00 [scsi_tmf_1]
    533 ?        I<     0:00 [xfsalloc]
    535 ?        I<     0:00 [xfs_mru_cache]
    536 ?        I<     0:00 [xfs-buf/vda1]
    537 ?        I<     0:00 [xfs-conv/vda1]
    538 ?        I<     0:00 [xfs-cil/vda1]
    539 ?        I<     0:00 [xfs-reclaim/vda]
    540 ?        I<     0:00 [xfs-blockgc/vda]
    542 ?        I<     0:00 [xfs-log/vda1]
    543 ?        S      2:57 [xfsaild/vda1]
    880 ?        I<     0:00 [nfit]
1636473 ?        I      0:01 [kworker/5:2-events_power_efficient]
1636635 ?        I      0:07 [kworker/7:0-events]
1636884 ?        I      0:00 [kworker/6:0-events]
1636886 ?        I      0:00 [kworker/2:3-events]
1637134 ?        I      0:00 [kworker/1:0-events]
1637224 ?        I      0:00 [kworker/2:0]
1637273 ?        I      0:00 [kworker/0:3-mm_percpu_wq]
1637275 ?        I      0:00 [kworker/u16:0-events_unbound]
1637290 ?        I      0:00 [kworker/6:2-mm_percpu_wq]
1637344 ?        I      0:00 [kworker/1:1]
1637352 ?        Ss     0:00 sshd: root [priv]
1637362 ?        I      0:00 [kworker/0:2-events]
1637501 ?        I      0:00 [kworker/4:1-events]
1637953 ?        I      0:00 [kworker/3:0-cgroup_pidlist_destroy]
1637956 ?        I<     0:00 [ib-comp-wq]
1637957 ?        I<     0:00 [kworker/u17:0]
1637958 ?        I<     0:00 [ib-comp-unb-wq]
1637960 ?        I<     0:00 [ib_mcast]
1637961 ?        I<     0:00 [ib_nl_sa_wq]
1637965 ?        I      0:00 [kworker/5:0]
1637976 ?        I      0:00 [kworker/4:0-xfs-sync/vda1]
1637979 ?        I      0:00 [kworker/7:2]
1637981 ?        I      0:00 [kworker/3:3-cgroup_destroy]
1637986 ?        I      0:00 [kworker/u16:1-events_unbound]
1638007 pts/0    S+     0:00 grep --color=auto \[			
			
			

使用 grep -v 排除所有内核进程,这样看着舒服一些。

		
[root@netkiller ~]# ps ax | grep -v '\['
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     3:08 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
    649 ?        Ss     0:21 /usr/lib/systemd/systemd-journald
    681 ?        Ss     0:02 /usr/lib/systemd/systemd-udevd
    711 ?        S<sl   0:04 /sbin/auditd
    716 ?        S<     0:01 /usr/sbin/sedispatch
    759 ?        Ss     0:03 /usr/bin/lsmd -d
    769 ?        Ss     0:00 /usr/sbin/smartd -n -q never
    770 ?        Ssl    0:01 /usr/lib/polkit-1/polkitd --no-debug
    779 ?        Ss     0:14 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
    788 ?        Ss     0:00 /usr/sbin/mcelog --ignorenodev --daemon --foreground
    794 ?        S      0:08 /usr/sbin/chronyd
    974 ?        Ss     0:08 /usr/lib/systemd/systemd-logind
   1023 ?        Ssl    1:03 /usr/sbin/NetworkManager --no-daemon
   1027 ?        Ssl   76:19 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P
   1189 ?        Ss     0:01 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc -oMACs=hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512 -oGSSAPIKexAlgorithms=gss-curve25519-sha256-,gss-nistp256-sha256-,gss-group14-sha256-,gss-group16-sha512-,gss-gex-sha1-,gss-group14-sha1- -oKexAlgorithms=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1 -oHostKeyAlgorithms=ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,ssh-rsa,ssh-rsa-cert-v01@openssh.com -oPubkeyAcceptedKeyTypes=ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,ssh-rsa,ssh-rsa-cert-v01@openssh.com -oCASignatureAlgorithms=ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-256,rsa-sha2-512,ssh-rsa
   1201 ?        Ss     0:00 /usr/sbin/atd -f
   1233 tty1     Ss+    0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
   1234 ttyS0    Ss+    0:00 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
   1461 ?        S<sl  22:04 /usr/local/aegis/aegis_update/AliYunDunUpdate
   1490 ?        S<sl 412:12 /usr/local/aegis/aegis_client/aegis_11_25/AliYunDun
   1652 ?        Ss     0:02 /usr/sbin/crond -n
   1702 ?        Ssl    1:25 /usr/sbin/rsyslogd -n
   4186 ?        Ssl   35:58 /usr/bin/containerd
   4200 ?        Ssl   26:56 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
 221773 ?        Ss     0:01 /usr/sbin/sssd -i --logger=files
 221775 ?        S      0:09 /usr/libexec/sssd/sssd_be --domain implicit_files --uid 0 --gid 0 --logger=files
 221776 ?        S      3:32 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
 298641 ?        Ssl   31:55 /usr/local/share/aliyun-assist/2.2.3.309/aliyun-service
 298799 ?        Ssl    5:34 /usr/local/share/assist-daemon/assist_daemon
1629762 ?        Ssl    0:23 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
1637356 ?        Ss     0:00 /usr/lib/systemd/systemd --user
1637358 ?        S      0:00 (sd-pam)
1637366 ?        S      0:00 sshd: root@pts/0
1637367 pts/0    Ss     0:00 -bash
1638004 pts/0    R+     0:00 ps ax
		
		
			

对于可疑进程一律找到它所在位置,先kill掉,然后去掉可执行权限,归档备份。

例如我们对 caddy 下手,首先查看进程位置 /usr/bin/caddy

				
[root@netkiller ~]# ps ax |grep caddy
1629762 ?        Ssl    0:23 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
1637983 pts/0    S+     0:00 grep --color=auto caddy
				
			

看看是否有系统启动服务

			
systemctl stop caddy
systemctl disable caddy
			
			

现在就禁用了,如果这个程序是手工安装没有systemd,我们就需要 chmod -x /usr/bin/caddy

以上是 caddy 为例,其他服务也都如此。

检查配置文件

确认服务器使用的是什么操作系统,然后用这个版本安装一个干净的环境,在新服务器和当前要检查的服务器上分别执行下面命令

			
[root@netkiller ~]# find /etc/ > etc.lst
[root@netkiller ~]# find /usr/etc/ > usr.etc.lst
[root@netkiller ~]# find /usr/local/etc/ > usr.etc.lst			
			
			

然后使用文件比较工具比较文件列表,差异的部分,就是新增的文件。你也可以讲两个服务器的 etc 目录复制出来,使用工具比较他们的差异。

14.3.5. 容器的检查

目前许多公司都在使用 Docker / Kubernetes 部署系统,其实容器并非安全,在容器镜像中藏点私货是非常容易的,Docker 官方提供了安全扫描工具

		
[root@netkiller ~]# docker scan
Docker Scan relies upon access to Snyk, a third party provider, do you consent to proceed using Snyk? (y/N)		
		
		

我们安装物理机所用的系统通常是去官网下载,很多容器的制作并为使用官方镜像,同时会做 md5sum 校验,所以是安全的。容器镜像安全更多是来自无序的继承,经过多次继承我们不知道里面做了那些变化,所以选择基础镜像非常重要。

		
[root@netkiller ~]# cat Dockerfile | grep FROM
FROM nginx:latest
		
		

如果不是官方镜像,需要格外注意

14.3.6. 云安全检查

云平台通常网络分成WLAN和LAN两个部分,有些平台WLAN 是挂载到 eth0 上,有些平台云主机只有内网IP,WLAN是映射到内网IP上。

采用的手段跟上面一样,扫描端口,检查安全组规则,弹性IP和SLB策略。

原则是,WLAN外网只允许通过特定端口例如80/443,剩下所有服务在LAN上通信。

工作交接期间,只开放80/443端口,完成交接后,并做了安全排查之后,逐渐开放需要的端口,建议限制来源IP地址,例如只允许从办公室访问。

14.3.7. 系统备份

以上检查的所有项的配置文件都需要备份一份,以防万一,这个万一存在很多不确定性因素,你懂的

14.3.8. 绘制网络和服务器/容器拓扑图

使用visio等软件绘制网络和服务器/容器拓扑图

14.3.9. 部署运作机制

这个步骤是搞清楚代码从开发到生产环境是怎么部署的,如果使用了CI/CD技术,就从持续集成和部署着手看,可以一目了然。如果是手工部署,要亲力亲为自己做一遍,同时将CI/CD就此机会做起来。

举一个例子,比如有一个项目教 api.netkiller.cn

代码库中找到这个项目

编译和打包

目前国内最主流搭配是前端 node 后端 java,当然也有少量项目使用 PHP、Python和Go,总体大同小异。

如果是 node.js 项目通常是 webpack 无非就是下面两步

			
npm install --registry=https://registry.npm.taobao.org
npm run build:prod
			
			

Java 项目

			
mvn clean package		
			
			
搞清楚配置文件

前端 NodeJS 项目配置通常只链接后端,配置涉及较少,相对容易掌握。

Java 项目配置文件放在 src/main/resources/ 中 Springboot 项目配置文件是 src/main/resources/application.yml,Springcloud 的配置文件是 src/main/resources/bootstrap.yml

也有使用 application.properties 和 bootstrap.properties

我们既要检查配置文件中都链接了那些服务,还要检查配置是否合理,例如链接池的最大链接数量,链接超时时间等等。

如果使用配置中心,需要进入配置中心查看配置文件

绘制业务关系拓扑图

走一遍业务逻辑,从域名进入网站到数据保存到数据,这中间经过了那些服务,他们的调用关系是什么,画一张图,让你一清二楚。

如果有链路追踪能让你更快完成这步工作,如果没有,这也是未来要做的工作,这时就需要结合各种配置文件,或者询问各种相关部门和人员来完成这个拓扑图。

备份
  • 备份代码
  • 备份配置文件

将备份过程放在CI/CD过程中,让备份自动化

14.3.10. 接手代码

程序猿常常自嘲是粪海狂蛆!陈年的粪缸,经过发酵、沉淀、分解已经没有屎尿的味道,你千万别去动它。

国内大部分项目都是平均三年经验的开发人写的,同时90后平均不到两年就会换工作,你别期望代码质量有多高,你别更别期望问同事能得到答案。

常态是,大部分情况下,只要修改代码就产生新bug!延伸阅读《程序猿说的「优化」是什么意思?》

代码审查

代码审查只是一句口号历来如此,很多团队都说在做,实际情况你懂的。但是此时一些对外的服务真的有必要做一次 code review,我的职业生涯中,曾经遇到过离职人员埋后门的情况。

经过前面的服务器排查,通过SSH登陆服务器搞破坏的可能性是极小的,更多的漏洞是代码漏洞和业务漏洞。

代码扫描

使用代码扫描工具,例如 SonarQube 扫描lib和引用第三方包的安全漏洞,及时升级第三方包,修复存在安全的代码。

如果你期待代码扫描能帮你找出业务漏洞,纯属扯淡,我们使用代码扫描更多是发现 pom.xml 中引用第三方库已知的 CVE 漏洞。

收缩技术栈

接手代码之后,首要解决的是能让它工作起来,然后着手优化代码,绝大多数人的思维是加法思维,他们会使用许多技术来完成一件事,这是错误的。

正确的做法是使用一种技术完成所有工作。