OpenSSH 可以使用tun/tap设备来创建一个加密隧道,SSH隧道类似mode TCP模式下的OpenVPN,对于有需求快速设置一个基于IP的VPN来说非常方便。使用SSH隧道的优点:
当然也有缺点:
这里还要说明一下二层和三层的区别:
在Linux中tun/tap都可以设置IP,只是模拟的工作层有区别,tun是模拟三层网络设备,收发的是IP包,无法处理以太网数据帧。tap模拟的是二层设备,收发的是以为网数据帧,更接近物理网卡,可以和物理网卡通过网桥绑定。我们日常用的wmware虚拟机中的nat网络,对应的就是tun,桥接网络对应的就是tap。
首先要使用ssh的二层和三层隧道,尽量保证系统差别不要太大,我这里两边都是oracle linux 8,SSH版本更新到最新。server端需要允许root登录和隧道,编辑/etc/ssh/sshd_config:
PermitRootLogin yes
PermitTunnel yes
#建议添加
TCPKeepAlive yes
PermitTunnel yes代表允许point-to-point (layer 3)和ethernet (layer 2)
在client端执行:
ssh -w any:any root@[server_ip]
如果客户端和服务器端没有其它的tun设备,就会在客户端和服务器端各生成一个名为tun0设备,指定any可以自动分配可用的设备。查看设备:
[root@centos8 ~]# ip addr
3: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
link/none
可以看到有个tun0 <POINTOPOINT,MULTICAST,NOARP>,这个设备是未激活的状态,如果用ifconfig命令查看,需要加上-a参数才能看到。
为安全起见,建议使用以下命令:
ssh -NTCf -w 5:5 root@[server_ip]
执行完该命令client和server各自会创建一个tun5的点对点设备,下一步就是需要激活设备并分配IP。
分配IP不要与服务器和客户端网段有冲突,这里假设:
客户端IP:10.0.0.2 tun5 服务器IP:10.0.0.1 tun5
服务器激活点对点设备并分配IP和路由:
ip link set tun5 up
ip addr add 10.0.0.1/32 peer 10.0.0.2 dev tun5
客户端同理:
ip link set tun5 up
ip addr add 10.0.0.2/32 peer 10.0.0.1 dev tun5
这时隧道已经建立成功,此时用查看一下状态:
[root@centos8 ~]# ip addr
14: tun5: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 10.0.0.1 peer 10.0.0.2/32 scope global tun5
可以看到比之前多了“UP,LOWER_UP”,说明已经激活。正常情况下客户端和服务器已经可以相互ping。
客户端用一条命令也能搞定:
ssh \
-o PermitLocalCommand=yes \
-o LocalCommand="ip link set tun5 up && ip addr add 10.0.0.2/32 peer 10.0.0.1 dev tun5 " \
-o TCPKeepAlive=yes \
-w 5:5 root@[server_ip] \
'ip link set tun5 up && ip addr add 10.0.0.1/32 peer 10.0.0.2 dev tun5'
如果服务器端有其它内网段,需要继续添加客户端路由才能ping通,例如,客户端想与服务器端网段10.0.12.0/24互通,需在客户端执行:
ip route add 10.0.12.0/24 dev tun5
按需添加即可,更改路由是高风险操作,需要格外小心,同时也要确保ssh连接不要中断。
由于linux中允许为tap设备设置ip,所以二层隧道和三层隧道也可以完全一样的进行配置。区别是tap设备可以和物理网卡进行绑定,也就是桥接,同时由于工作在二层,允许Arp通过,能支持STP生成树、PPP等协议。
在客户端执行:
ssh -o Tunnel=ethernet -w 6:6 root@[server_ip]
这里参数 -o 需要在 -w 前面,查看一下客户端和服务器的网卡:
[root@centos8 ~]# ip addr
20: tap6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
在ip命令中 tap6: <BROADCAST,MULTICAST>,和物理网卡显示的一样,说明模拟的是物理网卡。
二层可以进行网卡桥接,桥接可以多块网卡,也可以一块网卡,这里测试为了省事只用一块网卡,创建网桥有三种工具:
建议用ip命令建立:
ip link add br0 type bridge
将tap6加入网桥:
ip link set tap6 master br0
配置服务器端网桥IP信息并启动网桥:
ip address add 10.0.0.1/32 dev br0
ip link set tap6 up
ip link set br0 up
客户端流程一样,只是客户端的ip是10.0.0.2
在客户端测试ARP包能不能通过:
[root@oracle8 ~]# arping -I br0 10.0.0.1
ARPING 10.0.0.1 from 10.0.0.2 br0
Unicast reply from 10.0.0.1 [3A:E7:2F:3F:42:24] 193.222ms
Unicast reply from 10.0.0.1 [3A:E7:2F:3F:42:24] 191.903ms
如果是三层隧道,就无法使用arping。
看似很多内容,其实使用很简单,OpenSSH套件功能真强大。
参考文章 https://help.ubuntu.com/community/SSH_VPN https://www.cyberciti.biz/faq/centos-8-add-network-bridge-br0-with-nmcli-command/ https://gobomb.github.io/post/build-l2-l3-vpn-by-openssh/
6月 1日, 2021年
通常HTTP的性能分析是通过浏览器的开发者工具进行查看,但这种方式只能通过图形页面进行查看。如果想做性能监控或者在命令行下分析,可以通过curl命令来统计各阶段的耗时。我们先来看看一个HTTP请求的过程:
(图片来自cloudflare)
每次http请求经过这些过程: 客户端发起请求-->DNS解析-->TCP连接-->SSL等协议握手-->服务器处理-->内容传输-->完成
查看curl 命令的手册,curl命令支持以下阶段的时间统计:
我们常关注的HTTP性能指标有:
注意: 如果想分析HTTP性能的瓶颈,不建议使用带有重定向的请求进行分析,重定向会导致建立多次TCP连接或多次HTTP请求,多次请求的数据混在一起,数据不够直观,因此 time_redirect 对实际分析意义不大。
其中的运算关系:
用curl命令统计以上时间:
curl -w '\ntime_namelookup=%{time_namelookup}\ntime_connect=%{time_connect}\ntime_appconnect=%{time_appconnect}\ntime_redirect=%{time_redirect}\ntime_pretransfer=%{time_pretransfer}\ntime_starttransfer=%{time_starttransfer}\ntime_total=%{time_total}\n\n' -o /dev/null -s -L 'https://www.nixops.me/'
以上内容不够直观,curl -w参数支持模板,新建一个文件timing.txt,内容如下:
time_namelookup=%{time_namelookup}\n
time_connect=%{time_connect}\n
time_appconnect=%{time_appconnect}\n
time_redirect=%{time_redirect}\n
time_pretransfer=%{time_pretransfer}\n
time_starttransfer=%{time_starttransfer}\n
time_total=%{time_total}\n
使用模板在执行一次:
curl -w "@timing.txt" -o /dev/null -s -L 'https://www.nixops.me/'
将上述功能生成脚本stat.sh
#!/bin/bash
#author : will
#website: https://www.nixops.me
Default_URL=https://www.nixops.me
URL=${1:-$Default_URL}
Result=`curl -o /dev/null -s $URL \
-w \
'time_namelookup=%{time_namelookup}
time_connect=%{time_connect}
time_appconnect=%{time_appconnect}
time_redirect=%{time_redirect}
time_pretransfer=%{time_pretransfer}
time_starttransfer=%{time_starttransfer}
time_total=%{time_total}
'`
declare $Result
curl_timing(){
printf "\e[92mcURL Timing: \e[0m\n"
for i in $Result
do
IFS='='
printf "\e[96m%18s \e[0m: %10s \n" $i
done
}
stat_timing(){
Result_TCP=`printf "%.6f" $(echo $time_connect - $time_namelookup |bc -l)`
Result_TLS=`printf "%.6f" $(echo $time_appconnect - $time_connect |bc -l)`
Result_Server=`printf "%.6f" $(echo $time_starttransfer - $time_pretransfer |bc -l)`
Result_TTFB=`printf "%.6f" $(echo $time_starttransfer - $time_appconnect |bc -l)`
Result_Transfer=`printf "%.6f" $(echo $time_total - $time_starttransfer |bc -l)`
printf "\n\e[92mResource Timing: \e[0m\n"
printf "\e[96m%18s \e[0m: %.6f \n" "DNS Lookup" $time_namelookup
printf "\e[96m%18s \e[0m: %.6f \n" "TCP Connection" $Result_TCP
if [ `echo "$time_appconnect == 0"|bc` -eq 0 ]
then
printf "\e[96m%18s \e[0m: %.6f \n" "TLS Handshake" $Result_TLS
fi
printf "\e[96m%18s \e[0m: %.6f \n" "Server Processing" $Result_Server
printf "\e[96m%18s \e[0m: %.6f \n" "TTFB" $Result_TTFB
printf "\e[96m%18s \e[0m: %.6f \n" "Content Transfer" $Result_Transfer
printf "\e[96m%18s \e[0m: %.6f \n" "Finish" $time_total
}
curl_timing
stat_timing
执行一下:
# ./stat.sh https://www.baidu.com
cURL Timing:
time_namelookup : 0.004087
time_connect : 0.006480
time_appconnect : 0.022001
time_redirect : 0.000000
time_pretransfer : 0.022026
time_starttransfer : 0.025635
time_total : 0.025658
Resource Timing:
DNS Lookup : 0.004087
TCP Connection : 0.002393
TLS Handshake : 0.015521
Server Processing : 0.003609
TTFB : 0.003634
Content Transfer : 0.000023
Finish : 0.025658
从上述结果,就可以直观的分析出http各阶段的耗时,方便我们进行性能瓶颈。
参考文章:
https://cizixs.com/2017/04/11/use-curl-to-analyze-request/ https://blog.cloudflare.com/a-question-of-timing/ https://curl.se/docs/manpage.html https://github.com/reorx/httpstat
5月 25日, 2021年
Openssl命令用法比较多,整理了一下平时常用的命令,做了个流水账,方便以后复杂粘贴。
openssl genrsa -out nixops.me.key 2048
openssl rsa -in nixops.me.key -pubout -out nixops.me.crt
一条命令生成:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout nixops.me.key -out nixops.me.crt
验证私钥和公钥:
openssl rsa -check -in nixops.me.key
openssl x509 -text -noout -in nixops.me.crt
openssl genrsa -out nixops.me.key 2048
openssl req -new -sha256 -key nixops.me.key -out nixops.me.csr
查看csr 信息:
openssl req -noout -text -in nixops.me.csr
生成CA私钥:
openssl genrsa -out CAKey.pem 2048
生成CA证书:
openssl req -x509 -sha256 -new -nodes -key CAKey.pem -days 3650 -out CACert.pem
也可以使用不用交互,直接提供相关信息:
openssl req -x509 -sha256 -new -nodes -key CAKey.pem -days 3650 -out CACert.pem -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=myorganization/OU=nixps LTD/CN=nixops.me"
查看CA证书详细信息:
openssl x509 -in CACert.pem -text
使用CA签发证书:
openssl x509 -req -CA CACert.pem -CAkey CAKey.pem -CAcreateserial -in nixops.me.csr -out nixops.me.issue.crt -days 365 -sha256
查看签发者信息:
openssl x509 -noout -issuer -issuer_hash -in nixops.me.issue.crt
openssl genrsa -out nixops.me.pem 2048
openssl rsa -in nixops.me.pem -text -noout
openssl rsa -in nixops.pem -pubout -out pub.pem
openssl rsa -in pub.pem -pubin -text -noout
使用这种方式1024位的私钥可以加密小于86字节的文件,2048位的私钥可以加密小于214字节的文件。 用公钥加密:
openssl rsautl -encrypt -inkey pub.pem -pubin -in file.txt -out file.bin
用私钥解密:
openssl rsautl -decrypt -inkey nixops.pem -in file.bin
用公钥加密:
openssl smime -encrypt -aes256 -in Large.zip -binary -outform DEM -out Encrypted.zip pub.pem
用私钥解密:
openssl smime -decrypt -in Encrypted.zip -binary -inform DEM -inkey nixops.pem -out Large.zip
一般有以下几种标准格式:
先查看证书信息,在转格式:
openssl x509 -in cert.der -inform der -text -noout
openssl x509 -in cert.der -inform der -outform pem -out cert.pem
openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.pem -outform der -out cert.der
openssl pkcs12 -info -nodes -in site.pfx
openssl pkcs12 -in site.pfx -out site.pem -nodes
需要JDK中提供的keytool工具配合openssl,先用keytool转成PKCS12格式:
keytool -importkeystore -srckeystore cert.jks -destkeystore cert.pkcs -srcstoretype JKS -deststoretype PKCS12
在用openssl转成pem格式:
openssl pkcs12 -in cert.pkcs -out cert.pem
openssl rsa -in cert.key -out nopass.key
openssl x509 -noout -hash -in cert.pem
openssl s_client -connect www.baidu.com:443 -showcerts
查看本地证书:
openssl x509 -dates -noout -in file.pem #查看证书签发时间和有效期
openssl x509 -startdate -noout -in file.pem #查看签发时间
openssl x509 -enddate -noout -in file.pem #查看有效时间
openssl x509 -checkend 86400 -noout -in file.pem #检查证书是否在一天内过期,用echo $?即可判断
查看在线证书:
openssl s_client -connect www.baidu.com:443 -servername www.baidu.com 2> /dev/null | openssl x509 -noout -dates
提取过期时间:
openssl s_client -connect www.baidu.com:443 -servername www.baidu.com 2>/dev/null |openssl x509 -enddate -noout |cut -d "=" -f 2
用date命令转换一下日期格式:
date --date="$(openssl s_client -connect www.baidu.com:443 -servername www.baidu.com 2>/dev/null |openssl x509 -enddate -noout |cut -d "=" -f 2)" --iso-8601
协议有TLS 1.0(tls1)、TLS 1.1(tls1_1) TLS 1.2(tls1_2),在高版本的openssl中默认已经禁用了SSL V2(ssl2)、SSL V3(ssl3)
openssl s_client -connect www.baidu.com:443 -tls1
openssl s_client -connect www.baidu.com:443 -tls1_2 -cipher 'ECDHE-RSA-AES128-GCM-SHA256'
参考文章: https://jamielinux.com/docs/openssl-certificate-authority/index.html https://stackoverflow.com/questions/21297853/how-to-determine-ssl-cert-expiration-date-from-a-pem-encoded-certificate https://geekflare.com/openssl-commands-certificates/
5月 13日, 2021年
2020年12月8日,CentOS官方发布公告称CentOS 8将于2021年12月31日结束支持,取而代之的是CentOS Stream。
以前centos作为RHEL的重新编译版,即下游发型版: Fedora -> RHEL -> CentOS 现在是和Fedora一样专注于RHEL的上游测试分支: Fedora -> CentOS Stream -> RHEL
CentOS Stream发布方式改为滚动更新,不像传统的操作系统有着明确的系统版本号,而是在升级过程中使用来自上游的最新软件包版本以及内核功能等。其定位是吸收Fedora中测试稳定的软件,制作成相对稳定的滚动发型版,即给RHEL做测试,又为RHEL培养客户。对于稳定性要求不高的场景,可以直接从CentOS 8迁移至CentOS Stream。
迁移之前,先备份好数据及重要的配置!!备份好数据及重要的配置!!备份好数据及重要的配置!!
dnf update
重启后查看版本号:
cat /etc/redhat-release
CentOS Linux release 8.3.2011
dnf install centos-release-stream
将当前的CentOS 8源替换成CentOS Stream源:
dnf swap centos-{linux,stream}-repos
distro-sync工具会比对本地软件和CentOS Steam源中的软件及内核,并进行必要的升级、降级或者保持不变,这一步中有差异的软件选择Y替换成CentOS Stream提供的版本:
dnf distro-sync
这一步骤会下载比较多的软件并安装,耗时比较久。下载安装完成后,重启系统并验证版本:
cat /etc/redhat-release
CentOS Stream release 8
移除无用和冲突的软件包:
dnf autoremove
CentOS默认会保留5个旧内核,移除旧版的内核和旧版的kernel-headers、kernel-devel等软件包,有三种方式:
清除了旧内核之后,如果之前使用了内核模块的软件,如wireguard等,需重新配置。
检查并重新设置开启启动,如firewalld等软件。另外,由于很多系统内核、系统软件和库文件被替换或升级,有些配置可能被更改或者软件无法启动,需一一进行验证。
总体来说,过程比较简单,也比较容易迁移。但是迁移毕竟是高风险操作,容易导致软件无法启动及灵异问题,排查起来比较麻烦,有条件仍然建议重新安装。
红帽官方不建议将CentOS Stream用于生产环境中,随着CentOS Stream的发布,Red Hat宣布放宽RHEL系统的独立开发者订阅,允许最多免费使用16个RHEL系统。如果服务器比较多,可以考虑迁移到Oracle Linux、Rocky Linux、AlmaLinux等基于RHEL的下游系统。
5月 10日, 2021年
wireguard是Linus Torvalds为数不多夸过的技术,称赞它是:it's a work of art。
wireguard优点和缺点官网有很好的介绍,我简单总结一下,优点:
缺点:
总结一下,wireguard配置简单且安全高效,适合服务器之间互联。由于国内udp限速及特征明显,不适合个人当梯子用。
如果系统是BSD之类的系统安装在用户空间,直接安装即可,如果是linux系统强烈建议使用最新的发行版,并更新内核到最新。
Centos系列:
yum update -y
reboot
centos 7系统:
sudo yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum install yum-plugin-elrepo
centos 8系统:
dnf install elrepo-release epel-release -y
安装wireguard:
sudo yum install kmod-wireguard wireguard-tools -y
mkdir -p /etc/wireguard/
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
vim /etc/wireguard/wg0.conf
写入以下内容:
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = 生成的server_private.key内容
[Peer]
PublicKey = 客户端的client public.key内容
AllowedIPs = 10.10.0.2/32
客户端的公钥需在客户端生成,并替换这里的内容,已可以在执行一下2.1节中的命令,生成另外一对公私钥供客户端使用。
设置权限,只允许root读取wireguard内容:
chmod 600 /etc/wireguard/ -R
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
使以上配置生效:
sysctl -p
centos 7有firewalld和iptables两种防火墙,如果使用firewalld作为防火墙:
firewall-cmd --zone=public --permanent --add-masquerade
firewall-cmd --permanent --add-port=51820/udp
systemctl reload firewalld
如果使用iptables作为防火墙:
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
ip6tables -A FORWARD -i wg0 -j ACCEPT
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ip6tables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
可以使用wg-quick或者systemctl进行管理,使用wg-quick命令:
启动wireguard:
wg-quick up /etc/wireguard/wg0.conf
关闭wireguard:
wg-quick down /etc/wireguard/wg0.conf
wg-quick down wg0
或者使用systemctl命令:
systemctl start wg-quick@wg0.service
查看启动日志:
journalctl -eu wg-quick@wg0.service
设置为开机启动:
systemctl enable wg-quick@wg0.service
启动成功后,使用ifconfig命令即可看到wg0的网卡,使用wg命令可以看到详细的信息。
wireguard在各平台都有客户端,下载地址: https://www.wireguard.com/install/
如果开客户端是图形界面,一般打开客户端就有生成公私钥对的选项;如果是客户端也是linux等服务器系统,可以按上面服务器端的生成方法,使用已有的公私钥对也可以。
客户端配置文件:
[Interface]
PrivateKey = 客户端自己的私钥
Address = 10.10.0.2/32
DNS = 1.1.1.1,8.8.8.8
[Peer]
PublicKey = 服务器端的公钥
#PresharedKey = XXX # 可选
AllowedIPs = 0.0.0.0/0
Endpoint = 服务器公网地址:51820
PersistentKeepalive = 10
客户端有几个配置需注意:
启动客户端后,在服务器端使用wg命令查看是否有客户端信息,并测试客户端到服务器、服务器到客户端的连接情况。
多个客户端时,需在server端配置多个peer,每个peer指定独立的静态ip和各自的公钥。
wireguard支持PreUp、PostUp、PreDown、PostDown参数,可以在wireguard启动、关闭前后执行一些自定义脚本或命令,实现一些特殊的需求。
wiregard提供Table参数进行设置路由表,Table默认值是auto,由wireguard自动设置路由,也可以按需创建路由表,并设置策略路由,客户端和服务器端都可以设置该参数。在 [interface] 下面添加以下的配置即可:
Table = 1234
PostUp = ip rule add ipproto tcp dport 25 table 1234
PreDown = ip rule delete ipproto tcp dport 25 table 1234
AllowedIPs控制了哪些流量允许使用该vpn,未匹配的流量会直连。个人翻墙时会使用全局VPN,但服务器之间连接时,基本不会把wiregaurd当做全局VPN使用。设置这里就非常方便。
AllowedIPs = 0.0.0.0/0,::/0 表示所有ipv4及ipv6的流量都要走vpn,适合个人用户。 AllowedIPs = 10.10.0.0/24,192.168.1.0/24 表示只有目的IP是这两个网段时走wireguard,其余流量走服务器默认的路由。
VPN Kill Switch 持续监控客户端与VPN服务器的连接,连接意外断开时会阻止设备客户端访问网络。从而防止泄露客户端的隐私。很多商业VPN都提供该功能,实现起来很简单,通过PreDown、PostDown执行更改客户端的防火墙、路由表、或者网卡配置即可。
wireguard的客户端都会有连接的日志,查看wireguard服务器端日志只能通过查看内核日志的方方式,内核要支持Dynamic Debugging,正常情况下需编译内核开启CONFIG_DYNAMIC_DEBUG,有些发型版已经默认开启。可以执行以下命令进行查看:
mount | grep debug
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
如果和上面的显示一样,就说明已开启。配置开启调试日志:
modprobe wireguard
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
开启之后,可以通过以下两个命令查看日志:
dmesg -wH
journalctl -kf
由于wireguard对低版本内核支持不好,实际测试中centos 7系统日志很少,centos 8系统日志就比较详细,这也是为什么安装wireguard之前建议升级内核的原因。
报错1: linux做为客户端时启动wireguard报错: RTNETLINK answers: Operation not supported
该报错需重启服务器或客户端
报错2: vpn服务器ping客户端时报错: ping: sendmsg: Required key not available
该错最有可能是服务器端的peer部分AllowedIPs配置不对,网上一些教程使用SaveConfig=true,该配置是在关闭或重启wireguard时才添加配置,导致如果客户端连接后如果服务器端未重启,就会出现该错误,不建议使用saveConfig=true。
报错3: 服务器端ping客户端时提示: ping: sendmsg: Destination address required 一般是服务器端更改配置后,客户端未重新连接,客户端重新连接即可
报错4: 启动wireguard时报错: Error: Unknown device type. Unable to access interface: Protocol not supported 或执行 modprobe wireguard 命令报错: modprobe: FATAL: Module wireguard not found in directory
这个错误通常是因为升级内核导致的,wireguard的内核模块安装在旧版内核上,新内核没有wireguard模块,解决方法是卸载旧版内核、旧版kernel-header、旧版kernel-devel等,重新安装wireguard即可。
报错5: yum或dnf无法安装kmod-wireguard
dnf install kmod-wireguard
Repository epel is listed more than once in the configuration
Last metadata expiration check: 1:02:21 ago on Thu 13 May 2021 02:45:45 PM HKT.
Error:
Problem: cannot install the best candidate for the job
- nothing provides kernel(__skb_flow_dissect) = 0xd82bed9c needed by kmod-wireguard-3:1.0.20210424-1.el8_3.elrepo.x86_64
- nothing provides kernel(flow_keys_basic_dissector) = 0xa7e38f12 needed by kmod-wireguard-3:1.0.20210424-1.el8_3.elrepo.x86_64
- nothing provides kernel(ipv6_stub) = 0xf3965b90 needed by kmod-wireguard-3:1.0.20210424-1.el8_3.elrepo.x86_64
- nothing provides kernel(totalram_pages) = 0xde9360ba needed by kmod-wireguard-3:1.0.20210424-1.el8_3.elrepo.x86_64
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
此错误是因为centos stream系统默认没有wireguard导致,需执行以下命令启用COPR库中的wireguard:
dnf install epel-release
dnf copr enable jdoss/wireguard
dnf install wireguard-dkms wireguard-tools
综上,配置非常简单,功能可玩性高!
参考文章: https://www.wireguard.com/ https://www.linuxbabe.com/centos/wireguard-vpn-server-centos
1月 21日, 2021年
正常的服务器都是使用 用户名+密码或者用户名+ssh key的方式登录,配合防火墙及合理的ssh配置,能达到很好的安全性。但是无论密码还是ssh key都是固定不变的,一旦被渗透等就会导致登录信息泄露,这时如果启用了多因子认证,就能防止黑客通过ssh登录。多因子认证是在原有的认证基础上,在加一个或多个基于时间不断变化的验证码、或生物指纹、面部识别的认证,只要这个信息不泄漏,即使原认证信息泄露也无法登录。
最常见的多因子验证,就是谷歌的两步验证。类linux的系统中,很多软件都是使用pam模块做认证的,谷歌开源了google-authenticator-libpam工具,理论上支持pam认证的软件都可以启用谷歌两步认证。下面就说一下ssh配置两步认证的过程和一些玩法。
centos 的epel源中有现成的包,debian中也有,直接使用dnf就能安装,我这里使用编译的方式安装。
dnf install git autoconf automake make libtool gcc
在命令行显示二维码用到 libqrencode ,
dnf install qrencode
两步认证用到了pam认证框架,需安装pam-devel
dnf install pam-devel
编译:
git clone https://github.com/google/google-authenticator-libpam.git
cd google-authenticator-libpam
./bootstrap.sh
./configure
make
sudo make install
主要用到以下两个文件
TOTP是基于时间的,在初始化两步验证之前,先对一下时间,如果有ntpdate命令,执行:
ntpdate time.cloudflare.com
把这这个命令加到定时任务中,一定要确保服务器时间准确。
如果系统是redhat8,系统中ntp已经被chrony替代,执行以下命令:
dnf install -y chrony
systemctl enable chronyd
systemctl start chronyd
查看时间同步时间源服务器:
chronyc sources
查看同步状态:
chronyc tracking
准备工作做完后,就可以初始化两步验证,首先需要手机或个人电脑中安装两步验证的客户端,例如:谷歌验证器、authy等。
在服务器上执行:
google-authenticator
google-authenticator 初始化步骤:
第1个:是否想启用基于时间的令牌,选择y
第2个:是否更新认证文件(root用户是/root/.google_authenticator),由于第一次设置文件不存在,选择y
第3个:是否禁止多个用户公用认证口令,有可能会产生中间人欺骗,即令牌用过一次即失效,禁止选择y
第4个:默认1个口令的有效期是30s,为了防止主机时间和口令客户端时间不一致,最多允许客户端和服务器误差4分钟,服务器上已经设置时间同步,选择n
第5个:是否启用防暴力破解,30s内不得超过3次登陆测试,选择y
这里需要用手机客户端扫描生成的二维码,初始化完成后会生成两步验证的配置文件,root用户在/root/.google_authenticator,普通用户在/home/user/.google_authenticator,文件的属主要和用户一致,不然会导致无法登录。
和手动初始化一样,只是使用参数的方式,不需要交互,方便进行自动化和脚本调用
google-authenticator -t -d -r 3 -R 30 -w 3 -s /root/.google_authenticator
-t: 基于时间的令牌
-d: 不允许令牌重用
-r 3: 限制错误次数为3次
-R 30: 限制验证时间窗口为 30s
-w 3: 验证窗口为3个,当前验证令牌的前一个和后一个均是生效的,也就是允许误差
-s : 保存位置,默认为~/.google_authenticator
配置sshd_config,编辑 /etc/ssh/sshd_config,添加:
ChallengeResponseAuthentication yes
UsePAM yes
重启sshd
systemctl restart sshd
编辑 /etc/pam.d/sshd,在第一行添加:
auth required /usr/local/lib/security/pam_google_authenticator.so [authtok_prompt='请先输入两步验证码:' ] secret=/root/.google_authenticator no_increment_hotp
no_increment_hotp :不统计失败的两步认证,防止有被暴力破解时锁定用户。
配置好后,可以用ssh或者xshell客户端登录一下,登录过程:
ssh root@172.16.29.100
'请先输入两步验证码:'
Password:
Last login: Wed Jan 20 17:09:39 2021 from 172.16.29.1
[root@nixops.me ~]#
编辑 /etc/pam.d/sshd,在最后一行添加:
auth required /usr/local/lib/security/pam_google_authenticator.so nullok
通过以上的配置,ssh密码 + 谷歌两步验证的登录方式就配置完成了。
因为使用了pam框架,有一些基于pam的程序,都可以试着启用两步验证
编辑/etc/pam.d/su,找到开头这里:
#%PAM-1.0
auth required pam_env.so
auth sufficient pam_rootok.so
在 pam_rootok.so这一行下面,加入
auth required /usr/local/lib/security/pam_google_authenticator.so [authtok_prompt='请先输入两步验证码:' ] secret=/root/.google_authenticator no_increment_hotp
加入后,root切换至普通用户不需要两步验证,普通用户切换至root,或者普通用户之间切换需要先进行两步验证
sudo 实际上是以root用户执行命令,在pam的规则中指定一下user即可,编辑/etc/pam.d/sudo,在第一行加入
auth requisite /usr/local/lib/security/pam_google_authenticator.so [authtok_prompt='请先输入两步验证码:' ] secret=/root/.google_authenticator user=root
编辑/etc/pam.d/sshd,在顶部添加:
auth [success=1 default=ignore] pam_access.so accessfile=/etc/totp_access.conf
auth required /usr/local/lib/security/pam_google_authenticator.so [authtok_prompt='请先输入两步验证码:' ] secret=/root/.google_authenticator no_increment_hotp
规则文件/etc/totp_access.conf的内容为:
+ : ALL : 10.20.10.100
+ : ALL : 172.16.19.0/24
+ : ALL : LOCAL
- : ALL : ALL
安全不在于登录过程中多几道认证,但是对于某些要求较高或者特殊的场景下,可能会有需要多重认证的情况,三重认证包括以下认证方式:
和ssh密码认证的方式类似,只是把密码认证改成了ssh publickey + publickey password而已,配置思路也是一样,只是需要sshd_config中多加两条配置,用来指定登录使用的认证方式:
PubkeyAuthentication yes
AuthenticationMethods publickey,password publickey,keyboard-interactive
如果服务器中不只有一个用户,pam配置中可以使用变量${USER}来配置多用户,不需要为每个用户写一条pam配置,例如:
auth required pam_google_authenticator.so secret=/home/${USER}/.ssh/google_authenticator nullok
如果想做自动化,可以定制一个.bash_profile文件,将这个.bash_profile文件放到/etc/skel/中,这样每次创建用户后就会复制到用户目录下,当用户第一次登录后,调用其中的脚本生成/home/${USER}/.google_authenticator,从而自动绑定两步认证,这里只提供思路,不做具体实现。
参考文章: https://www.redhat.com/sysadmin/mfa-linux https://wiki.archlinux.org/index.php/Google_Authenticator https://www.digitalocean.com/community/tutorials/how-to-set-up-multi-factor-authentication-for-ssh-on-centos-8
1月 18日, 2021年
在油管上看linux大神在芬兰阿尔托大学演讲视频时,突然发现了一个名场面,有观众说英伟达对Linux系统支持不够好,大神一通说明后来了句:Nvidia,FXXK YOU! 原视频在下面,需要梯子,时间是49:56。
这么出名的场面,就想做成表情包玩玩,于是就想到了曾经把我折磨的死去活来的ffmpeg。
1. 下载视频
首先需要使用youtube-dl下载原视频,先列出视频可下载的格式:
youtube-dl -F 'https://www.youtube.com/watch?v=MShbP3OpASA'
[youtube] MShbP3OpASA: Downloading webpage
[info] Available formats for MShbP3OpASA:
format code extension resolution note
249 webm audio only tiny 55k , opus @ 50k (48000Hz), 21.72MiB
250 webm audio only tiny 69k , opus @ 70k (48000Hz), 25.71MiB
140 m4a audio only tiny 131k , m4a_dash container, mp4a.40.2@128k (44100Hz),
58.10MiB
251 webm audio only tiny 135k , opus @160k (48000Hz), 46.92MiB
160 mp4 256x144 144p 109k , avc1.4d400c, 25fps, video only, 17.00MiB
278 webm 256x144 144p 114k , webm container, vp9, 25fps, video only,
39.68MiB
242 webm 426x240 240p 225k , vp9, 25fps, video only, 44.87MiB
133 mp4 426x240 240p 244k , avc1.4d4015, 25fps, video only, 41.77MiB
243 webm 640x360 360p 415k , vp9, 25fps, video only, 100.11MiB
134 mp4 640x360 360p 583k , avc1.4d401e, 25fps, video only, 86.82MiB
244 webm 854x480 480p 758k , vp9, 25fps, video only, 184.20MiB
135 mp4 854x480 480p 1199k , avc1.4d401e, 25fps, video only, 138.93MiB
247 webm 1280x720 720p 1506k , vp9, 25fps, video only, 251.06MiB
136 mp4 1280x720 720p 2117k , avc1.4d401f, 25fps, video only, 220.55MiB
248 webm 1920x1080 1080p 2633k , vp9, 25fps, video only, 381.07MiB
137 mp4 1920x1080 1080p 3637k , avc1.640028, 25fps, video only, 318.59MiB
18 mp4 640x360 360p 389k , avc1.42001E, 25fps, mp4a.40.2@ 96k (44100Hz), 178.03MiB
22 mp4 1280x720 720p 608k , avc1.64001F, 25fps, mp4a.40.2@192k (44100Hz) (best)
我们做gif表情包,不需要声音,下载一个高质量的Viedo only视频即可,下载指定视频:
youtube-dl -f 137 -o linux.mp4 'https://www.youtube.com/watch?v=MShbP3OpASA'
2. 裁剪视频
下载好之后,找到要裁剪的时间段:49:58,裁剪时长3秒,进行裁剪:
ffmpeg -i linux.mp4 -ss 00:49:58.00 -t 00:00:03.00 linux_3s.mp4
3. 添加文字
ffmpeg中可以用drawtext filter为视频添加水印或添加文字,需要编译ffmpeg添加支持:
查看ffpmeg编译参数:
ffmpeg -version
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers
built with Apple clang version 12.0.0 (clang-1200.0.32.28)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.3.1_9 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100
参数没有问题,就可以使用drawtext filter添加文字了:
ffmpeg -i linux_3s.mp4 -vf "drawtext=fontcolor=yellow:fontsize=100:fontfile=msyh.ttf:text='英伟达不讲武德':x=(w-text_w)/2:y=h-th-20" -y out_3s.mp4
设置文字位置:
如果有多句话,可以指定时间段进行添加:
ffmpeg -i linux_3s.mp4 -vf "drawtext=enable='between(t,1,2.5)':fontcolor=yellow:fontsize=100:fontfile=msyh.ttf:text='英伟达不讲武德':x=(w-text_w)/2:y=h-th-20" -y out_3s.mp4
enable='between(t,1,2.5)' 指定的是在1s-2.5s之间添加文字。
4. 缩放视频尺寸
裁剪好后的源视频是1920x1080 1080p格式的,做成gif是全屏的比较大,需要先进行缩放:
ffmpeg -i out_3s.mp4 -vf scale=360:-2 small_3s.mp4
注意 sacle
值必须是偶数,这里的 -2
表示要求压缩出来的视频尺寸长宽都保持为偶数.如果需要保持长宽比,根据宽度值自适应高度,可以使用 -1
。
我这里只进行缩小就可以了,你也可能有加速播放和慢速播放的需要,也可以用实现。
4.1 加倍速播放视频
ffmpeg -i out_3s.mp4 -filter:v "setpts=0.5*PTS" out_speedup.mp4
4.2 定义帧率 16fps
ffmpeg -i out_3s.mp4 -r 16 -filter:v "setpts=0.125*PTS" -an out_16fps.mp4
4.3 慢倍速播放视频
ffmpeg -i out_3s.mp4 -filter:v "setpts=2.0*PTS" out_slowdown.mp4
5.将视频 MP4 转化为 GIF
经过以上步骤,已经有了我们处理完成的视频文件,只需要转换成gif即可:
ffmpeg -i small_3s.mp4 small.gif
转化成gif默认转换是中等质量的,压缩的比较厉害,可以修改比特率提高gif质量:
ffmpeg -i small_3s.mp4 -b 2048k small.gif
统过以上步骤就完成了我们要制作的gif,ffmpeg的生态比较丰富,目前很多在线制作表情包的网站和一些Telegram上的bot,就是通过ffmpeg进行制作。也可以找其它的视频进行制作,比如,张学友:食屎啦你、有钱真的可以为所欲为、王镜泽: 真香 等等。
附上最终做好的gif,和裁剪好的3秒源视频:
11月 26日, 2020年
简单来说,linux的内存分为虚拟内存和物理内存,进程在申请内存时,首先申请的是虚拟内存,等到真正需要的时候才去申请物理内存。内核通过这种机制避免内存的浪费,实现了按需分配物理内存。
所以虚拟内存可以大于实际的物理内存,超过这部分就是memory overcommit,而一旦进程需要申请的物理内存超过实际内存和交换空间的总和,内核就会用OOM Killer,选择杀掉一个或部分进程,保障系统和其它进程有可用的内存。
在 Linux 中,可以通过内核参数vm.overcommit_memory去控制是否允许 overcommit:
linux内核会为每个进程算一个分数,发生OOM时分数最高的进程会被kill掉,主要看以下几个参数:
只要允许overcommit,就会有oom killer发生,所以关闭overcommit就可以关闭OOM Killer:
sysctl -w vm.overcommit_memory=2
echo "vm.overcommit_memory=2" >> /etc/sysctl.conf
如果不想关闭OOM,也可以直接调整相应进程的oom_score_adj和oom_adj值,来按需进行设置OOM的优先级:
echo -1000 > /proc/PID/oom_score_adj
或者:
echo -17 > /proc/PID/oom_adj
通过脚本计算一下所有进程的oom_score和oom_score_adj,就可以找出最可能产生OOM的进程,系统进程的OOM score是0,需要排除,脚本是网上找的,内容如下:
#!/bin/bash
printf 'PID\tOOM_Score\tOOM_Adj\tCommand\n'
while read -r pid comm;
do
[ -f /proc/$pid/oom_score ] && [ $(cat /proc/$pid/oom_score) != 0 ] && printf '%d\t%d\t\t%d\t%s\n' "$pid" "$(cat /proc/$pid/oom_score)" "$(cat /proc/$pid/oom_score_adj)" "$comm";
done < <(ps -e -o pid= -o comm=) | sort -k 2nr
学习的时候需要测试OOM,可以用以下方法手动触发OOM
for b in {0..99999999}; do a=$b$a; done
for x in {1..10}; do echo "Start trigger OOM-killer: $x"; bash -c "for b in {0..99999999}; do a=$b$a; done"; done
#!/bin/bash
oom(){
echo "Start trigger OOM-killer" && bash -c "for b in {0..99999999}; do a=$b$a; done"
}
oom &
ppid=`ps -ef |grep -v grep |grep 99999999 |awk '{print $3}'`
pid=`pgrep -P $ppid`
echo ppid: $ppid
echo fork pid: $pid
while [ -d "/proc/$pid" ];
do
echo $pid : oom_score: `cat /proc/$pid/oom_score`
done
OOM发生时,会在/var/log/message中出现如下日志:
Nov 26 10:51:25 nixops.me kernel: Out of memory: Kill process 18903 (bash) score 645 or sacrifice child
Nov 26 10:51:25 nixops.me kernel: Killed process 18903, UID 0, (bash) total-vm:3640712kB, anon-rss:3441992kB, file-rss:4kB
zabbix之类的监控软件可以通过关键字过滤,来进行监控。如果有ELK这类的日志系统,可以收集messages日志,用logstash插件进行告警。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。