ubuntu 20.04升级到ubuntu 22.04报错“update-alternatives: 错误: /var/lib/dpkg/alternatives/mpi 损坏:次要链接与主链接 /usr/bin/mpicc 相同”

ubuntu 20.04 升级到 ubuntu 22.04 报错,报错内容如下:

解决方法:

Flutter构建Linux应用

从3.0之后的版本,flutter已经正式支持构建Linux应用

条件

  • ubuntu 22.04
  • Android Studio Chipmunk |  2021.2.1
  • flutter sdk 3.x

方法

1. 打开Linux的平台支持

输入如下指令(如下命令可以使用flutter config查看,2.10以上的版本默认开启

可以使用flutter doctor查看情况。

安装编译依赖

2. 在旧项目中添加Linux平台支持

在项目地址输入如下指令

注意: 项目的名称必须是全小写,如果出现大小写则会报错

3. 构建Linux项目

4. 报错

出现这个问题

参考链接


SSH默认不支持RSA了

今天升级ubuntu 22.04/Window 11后最基本的ssh登陆突然出问题了, 提示有几种:

一查发现…好嘛, openssh觉得ssh-rsa加密方式不安全, 直接从8.8开始默认不允许这种密钥用于登陆了

解决方法是可以在~/.ssh/config里面加这么一段解决:

第一行说明对所有主机生效, 第二行是将 ssh-rsa 加会允许使用的范围, 第三行是指定所有主机使用的都是 ssh-rsa 算法的key

实测两行都得要写才行, 没有第二行提示没有 ssh-rsa 这么个类型

没有第三行就提示 sign_and_send_pubkey: no mutual signature supported

参考链接


ssh默认不支持rsa了

polkit的pkexec中的本地权限提升漏洞 (CVE-2021-4034)

漏洞简介

漏洞编号: CVE-2021-4034

漏洞产品: PolKit (pkexec)

影响版本: 影响2009年 - 今的版本(当前0.105)

源码获取:

​ 或 https://launchpad.net/ubuntu/bionic/+package/policykit-1

继续阅读polkit的pkexec中的本地权限提升漏洞 (CVE-2021-4034)

How to repair a broken/unmountable btrfs filesystem

最近磁盘上的Btrfs分区在调整大小的时候,报错:

How to repair a broken/unmountable btrfs filesystem

The below are the recommended steps for any major btrfs filesystem issue, especially if its unmountable. Reading dmesg or syslog might help you identify which step you could skip to in order to fix a particular problem, but the initial steps are normally useful regardless as btrfs scrub is a very safe repair tool.

  • Boot to a suitable alternative system, such as a rescue shell, different installation of openSUSE, a liveCD, or an openSUSE installation DVD. The installation DVD for the version of openSUSE you are running is usually a good choice as it will certainly use the same kernel/btrfs version. A recent Tumbleweed disk might be better as it will include newer kernel/btrfs
  • Go to a suitable console and make sure you do the below as root
  • Try to mount your partition to /mnt, just to confirm it's really broken

  • If it mounts - are you sure it's broken? if Yes - run

to scrub the system, and

to monitor it

  • If it doesn't mount, try to scrub the device just in case it works

and

to monitor. Once complete, try mounting, if yes, you're fixed.

  • If scrubbing is not an option or does not resolve the issue

then instead try mount -o usebackuproot

Warning: All of the above steps are considered safe and should make no destructive changes to disk. If the above doesn't fix things for you, you can continue with the below steps but the situation is serious enough to justify a bug report, please!

  • Run "btrfs check <device>"

This isn't going to help, but save the log somewhere, it will be useful for the bug report.

  • Seriously consider running "btrfs restore <device> <somewhereto copy data>"

This won't fix anything but it will scan the filesystem and recover everything it can to the mounted device. This especially useful if your btrfs issues are actually caused by failing hardware and not btrfs fault.

  • Run "btrfs rescue super-recover <device>"

Then try to mount the device normally. If it works, stop going.

  • Run "btrfs rescue zero-log <device>"

Then try to mount the device normally. If it works, stop going.

  • Run "btrfs rescue chunk-recover <device>"

This will take a LONG while. Then try to mount the device normally. If it works, stop going.

  • If you didn't run it earlier, be sure to now run "btrfs restore <device> <somewhere to copy data>"

  • Failure to use btrfs restore at this point but continuing to attempt repairs means you are at a very high risk of data loss. It is advisable to use btrfs restore to recover as much data as possible before continuing.

Warning: The above tools had a small chance of making unwelcome changes. Below this point there is a higher risk of damage. Do not continue unless you're prepared to accept the consequences of your choice.

  • Now, ONLY NOW, try btrfsck aka "btrfs check --repair <device>"

最后,上面的步骤都不能解决问题,因此最终是把磁盘上的文件全部拷贝出来,然后重新格式化分区,再把文件全部拷贝回去,解决问题。

参考链接


运维中tcp_tw_recycle net.ipv4.tcp_timestamps引发的坑

NAT环境下,遇到因为tcp_tw_recycle=1和net.ipv4.tcp_timestamps=1引起 Nginx upstream timed out 后,一直没在遇见,今天在朋友的阿里云环境下又重新再一次出现;因此在这炒一次冷饭,让运维新手或者刚上云的朋友大概了解一下,避免再一次采坑。

故障情况:

阿里云账号A的A机房,内网里面部署两台Nginx,通过网络出口(NAT),代理用户访问到阿里云账号B的B机房服务。A机房的Nginx出现:upstream timed out 。

故障的诱因是:net.ipv4.tcp_timestamps=1

抓包图:

注意,这个选项生效的前提是,报文的发出方必须在TCP头部的可选项中增加时间戳字段,否则这个设置是不生效的。

直接上当年的笔记:

先看看TCP IP 对tw的一些解析:
RFC 1323里有这样的定义:

大概的中文意思就是:TCP协议中有一种机制,缓存了每个主机(即ip)过来的连接最新的timestamp值。这个缓存的值可以用于PAWS(Protect Against Wrapped Sequence numbers,是一个简单的防止重复报文的机制)中,来丢弃当前连接中可能的旧的重复报文。而Linux实现这个机制的方法就是同时启用net.ipv4.tcp_timestamps和net.ipv4.tcp_tw_recycle 这两个选项。
这种机制在 客户端-服务器 一对一的时候,没有任何问题,但是当服务器在负载均衡器后面时,由于负载均衡器不会修改包内部的timestamp值,而互联网上的机器又不可能保持时间的一致性,再加上负载均衡是会重复多次使用同一个tcp端口向内部服务器发起连接的,就会导致什么情况呢:

负载均衡通过某个端口向内部的某台服务器发起连接,源地址为负载均衡的内部地址——同一假如恰巧先后两次连接源端口相同,这台服务器先后收到两个包,第一个包的timestamp被服务器保存着,第二个包又来了,一对比,发现第二个包的timestamp比第一个还老——客户端时间不一致。服务器基于PAWS,判断第二个包是重复报文,丢弃之。

反映出来的情况就是在服务器上抓包,发现有SYN包,但服务器就是不回ACK包,因为SYN包已经被丢弃了。为了验证这一结果,可以执行netstat -s | grep timestamp 命令,看输出里面passive connections rejected by timestamp 一项的数字变化。

tcp_ipv4.c中,在接收SYN之前,如果符合如下两个条件,需要检查peer是不是proven,即per-host PAWS检查:

  • 收到的报文有TCP option timestamp时间戳
  • 本机开启了内核参数net.ipv4.tcp_tw_recycle

解决办法:

tcp_tw_recycle=0 或(和)net.ipv4.tcp_timestamps=0同时从4.10内核开始,官方修改了时间戳的生成机制,所以导致 tcp_tw_recycle 和新时间戳机制工作在一起不那么友好,同时 tcp_tw_recycle 帮助也不那么的大。

此处的时间戳并不是我们通常意义上面的绝对时间,而是一个相对时间。很多情况下,我们是没法保证时间戳单调递增的,比如业务服务器之前部署了NAT,LVS等情况。相信很多小伙伴上班的公司大概率实用实用各种公有云,而各种公有云的 LVS 网关都是 FullNAT 。所以可能导致在高并发的情况下,莫名其妙的 TCP 建联不是那么顺畅或者丢连接。

而这也是很多优化文章中并没有提及的一点,大部分文章都是简单的推荐将net.ipv4.tcp_tw_recycle设置为1,却忽略了该选项的局限性,最终造成严重的后果(比如我们之前就遇到过部署在nat后端的业务网站有的用户访问没有问题,但有的用户就是打不开网页)。

参考链接


certbot-auto不再支持所有的操作系统,新的ssl证书方法

最近在一台服务器执行letsencrypt-auto命令出现错误:

系统不再被支持!!!

查看certbot(https://github.com/certbot/certbot/releases)

2021年1月的更新日志:

可知:

certbot-auto不再支持所有的操作系统!根据作者的说法,certbot团队认为维护certbot-auto在几乎所有流行的UNIX系统以及各种环境上的正常运行是一项繁重的工作,加之certbot-auto是基于python 2编写的,而python 2即将寿终正寝,将certbot-auto迁移至python 3需要大量工作,这非常困难,因此团队决定放弃certbot-auto的维护。

既然如此,现在我们还能继续使用certbot吗?certbot团队使用了基于snap的新的分发方法。

1. 环境
操作系统:CentOS 7

Webserver:Nginx

2. 安装letsencrypt
2.1. 安装letsencrypt之前,需要先安装snaps

a. 先安装epel

b. 安装snapd

c. 启用snapd.socket

d. 创建/var/lib/snapd/snap/snap之间的链接。

e. 退出账号并重新登录,或者重启系统,确保snap启用。

f. 将snap更新至最新版本。

2.2. 卸载已安装的certbot

如果之前在系统上已经部署过certbot,则需要先将其进行卸载。

a. 卸载certbot

b. 根据certbot安装位置删除相关文件。

c. 删除certbot附加软件包。

2.3. 安装certbot

a. 通过snap安装certbot

b. 创建/snap/bin/certbot的软链接,方便certbot命令的使用。

3. letsencrypt的使用
3.1. 获取证书。

a. 生成证书。

确保nginx处于运行状态,需要获取证书的站点在80端口,并且可以正常访问。

b. 更新nginx配置并重启nginx

3.2. 更新证书。

ubuntu系统的话,使用如下命令方式安装:

参考链接


certbot-auto不再支持所有的操作系统,新的ssl证书方法

Centos 设置httpd-2.2 or httpd-2.4 MPM模式

MPM多进程处理模块

MPM分为三种模式:

1,prefork

进程模型,每个进程处理一个请求,模式:父进程——————>多个子进程——————>一个子进程处理一个请求

2,worker

线程模型,每个进程衍生出多个线程,每个线程处理一个请求,模式:父进程——————>多个子进程——————>每个子进程衍生多个线程------->一个线程处理一个请求任务

3,event

事件驱动模型,一个进程处理多个任务,模式:父进程————————>多个子进程-------->一个子进程处理多个请求

centos6 httpd-2.2 MPM设置

修改文件

/etc/sysconfig/httpd

默认为prefork模式

配置后重启httpd server生效

centos7 httpd-2.4 MPM设置

修改文件 /etc/httpd/conf.modules.d/00-mpm.conf

模式参数配置详解

参考链接


Centos 设置httpd-2.2 or httpd-2.4 MPM模式

fail2ban with OpenVPN(ubuntu 20.04)

This page describes how to set up fail2ban with OpenVPN 2.4.7 (tested on ubuntu 20.04)

Create /etc/fail2ban/filter.d/openvpn.conf containing:

Create /etc/fail2ban/jail.local containing:

To effect the configuration change:

To test the configuration change, check /var/log/fail2ban.log initially for service start messages and later for WARNING [openvpn] Ban and Unban messages.

参考链接


HOWTO fail2ban with OpenVPN

iptables之recent模块小结(ubuntu 16.04/20.04)

iptables的recent模块用于限制一段时间内的连接数, 是谨防大量请求攻击的必杀绝技! 善加利用该模块可充分保证服务器安全。

recent常用参数

  • --name      设定列表名称,即设置跟踪数据库的文件名. 默认DEFAULT;
  • --rsource   源地址,此为默认。 只进行数据库中信息的匹配,并不会对已存在的数据做任何变更操作;
  • --rdest       目的地址;
  • --seconds  指定时间内. 当事件发生时,只会匹配数据库中前"几秒"内的记录,--seconds必须与--rcheck或--update参数共用;
  • --hitcount   命中次数. hits匹配重复发生次数,必须与--rcheck或--update参数共用;
  • --set           将地址添加进列表,并更新信息,包含地址加入的时间戳。 即将符合条件的来源数据添加到数据库中,但如果来源端数据已经存在,则更新数据库中的记录信息;
  • --rcheck     检查地址是否在列表,以第一个匹配开始计算时间;
  • --update    和rcheck类似,以最后一个匹配计算时间。 如果来源端的数据已存在,则将其更新;若不存在,则不做任何处理;
  • --remove   在列表里删除相应地址,后跟列表名称及地址。如果来源端数据已存在,则将其删除,若不存在,则不做任何处理;

recent模块需要注意的地方

  1. 目录/proc/net/下的xt_recent目录是在启用recent模块之后才有的,如果没有在iptables中使用recent模块,/proc/net/目录中是没有xt_recent目录的;
  2. 因recent模块最多只能记录20条记录,所以当源发送的数据包超过20后,recent模块的计数器会立刻减掉20,这也就是为什么old_packets的值就总是处于1-20之间;
  3. 如果配合seconds参数使用的是--rcheck参数而不是--update,则recent模块会从收到第一个数据包开始计算阻断时间,而--update是从收到的最后一个数据包开始计算阻断时间,即如果服务器在8点收到了源发出第一个icmp数据包,在8点15分收到源发出的第20个数据包,如果使用的是--rcheck参数,那么8点半的时候,用户就又可以发送icmp数据包了,如果使用是--update参数,则用户必须等到8点40才能发送icmp数据包;
  4. 当源发送数据包的个数大于或等于recent模块的hitcount参数所指定的值时,相应的iptables规则才会被激活;

recent命令大体有如下三个排列组合

  • --set句在前,--update(或--rcheck)句在后;
  • --update(或--rcheck)句在前,--set句在后;
  • --set句带或不带-j ACCEPT。

基本是上面这三项的排列组合;

下面通过几个案例进行说明

1)  利用iptables的recent模块来抵御简单的DOS攻击, 下面以限制ssh远程连接为例

以上三条规则的解释如下:

  1. 利用connlimit模块将单IP的并发设置为3;会误杀使用NAT上网的用户,可以根据实际情况增大该值;
  2. 利用recent和state模块限制单IP在300s内只能与本机建立3个新连接。被限制一分钟后即可恢复访问。
  3. 第一句是记录访问tcp 22端口的新连接,记录名称为SSH, --set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
  4. 第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。      --update 是指每次建立连接都更新列表;      --seconds必须与--update同时使用      --hitcount必须与--update同时使用
  5. 可以使用下面的这句记录日志:

recent模块可以看作iptables里面维护了一个地址列表,这个地址列表可以通过"--set"、"--update"、"--rcheck"、"--remove"四种方法来修改列表,每次使用时只能选用一种。 还可附带"--name"参数来指 定列表的名字(默认为DEFAULT),"--rsource"、"--rdest"指示当前方法应用到数据包的源地址还是目的地址(默认是前者)。recent语句都带有布尔型返回值,每次执行若结果为真,则会执行后续的语句,比如"-j ACCEPT"之类的。"--seconds"参数表示限制包地址被记录进列表的时间要小于等于后面的时间。

基于上面的说明,现在来看四个基本方法的作用:

  • --set       将地址添加进列表,并更新信息,包含地址加入的时间戳。
  • --rcheck  检查地址是否在列表。
  • --update  跟rcheck一样,但会刷新时间戳。
  • --remove 就是在列表里删除地址,如果要删除的地址不存在就会返回假。

例1:限制无法ssh直接连接服务器,需先用较大包ping一下,此时在15秒内才可以连接上

以上命令解说

  1. 将INPUT链默认策略置为DROP,当包走完INPUT链而没被拿走时就会丢弃掉;
  2. 本地localhost的包全部接受;
  3. 对于已建立连接或是与已连接相关的包都接受,服务器对外连接回来的包一般都走这条;基本环境已经配好了,现在开始要为连接到服务器的ssh打开通路。
  4. icmp类型 8 是ping包;指定包大小为 128 字节;recent用的列表名称为SSHOPEN,列表记录源地址。符合上述条件的数据包都接收。如果ping包内容为 100 字节,则加上IP头, ICMP头的 28 字节,总共 128 字节。
  5. 接受一般的ping包;
  6. 对连接ssh 22端口的连接进行处理,来源于SSHOPEN源地址列表并且在列表时间小于等于15秒的才放行。

例2:  限制每ip在一分钟内最多对服务器只能有8个http连接

以上命令解说

  1. 192.168.10.10是服务器ip
  2. 参数-I,将本规则插入到 INPUT 链里头的最上头。只要是 TCP连接,目标端口是80,目标 IP是我们服务器的IP,刚刚新被建立起来时,我们就将这个联机列入 httpuser 这分  清单中;
  3. 参数-A,将本规则附在 INPUT 链的最尾端。只要是60秒内,同一个来源连续产生多个联机,到达第9个联机时,我们对此联机留下Log记录。记录行会以 HTTP attack 开头。  每一次的本规则比对, –update 均会更新httpuser清单中的列表;
  4. 参数-A,将本规则附在 INPUT 链的最尾端。同样的比对条件,但是本次的动作则是将此连接丢掉;
  5. 所以,这三行规则表示,我们允许一个客户端,每一分钟内可以接上服务器8个。具体数值可以看运维者决定。这些规则另外也可以用在其它对外开放的网络服务上,例如port  22 (SSH), port 25 (smtp email)。

2) 对连接到服务器B的SSH连接进行限制,每个IP每小时只限连接5次

服务器A连接服务器B的SSH服务的数据包流程,假设以下数据包是在一小时(3600秒)内到达服务器B(iptables配置如上)的:

  1. 当这个服务器A的第1个SSH包到达服务器B,规则1检查SSHPOOL列表中这个源IP是否有hitcount,因为是第一个包,显而易见,列表是0,规则1判定这个数据包不必执行      DROP,并且也不处理这个数据包,将数据包转给下条规则。
  2. 规则2将这个数据包计入SSHPOOL列表,就是做+1,因为规则中有-j ACCEPT,规则2放行这个包。
  3. 第1个数据包进入服务器B,不用再在iptables里转了。
  4. 当第2个SSH包到达服务器B,规则1检查SSHPOOL列表的hitcount,发现是1没有超过5,于是判定不执行DROP并转给下条规则处理。
  5. 规则2在SSHPOOL中+1,并放行,第2个数据包进入服务器B。
  6. 第3、4、5个包同上。 g) 第6个包到达服务器B,规则1检查SSHPOOL列表中的hitcount,发现是5了已经连接5次了,于是规则2执行DROP,不必再转给下条规则了丢弃该包。 h) 第7、8…个包同上。

实际上recent的处理更为复杂, 从上面的流程可以看出,--set的功能在于计录数据包,将源IP加入列表。--rcheck(update)的功能在于判定数据包在seconds和hitcount条件下是否要DROP。

如果采用下面的配置, 则必须在INPUT链的默认策略为ACCEPT的情况下才能生效并使用, 否则(即INPUT链的默认策略为DROP)所有的SSH包都被丢弃了!!!!

这个命令与上面命令的区别在于:set句在前,且set句不带-j ACCEPT。这导致数据包的流程也不同。

  1. 第1个数据包到达规则1后马上计入SSHPOOL列表,并且规则1因为没有-j ACCEPT,直接将数据包转给下条规则。规则2拿到这个数据包后检查SSHPOOL列表,发现是1,也  不处理这个包,转给下条规则。如果后续的规则都没有再处理这个数据包,则最后由INPUT链的默认策略ACCEPT处理。由于上面的策略是DROP,所以丢弃该包,于是这两行命令在我的服务器上不能用。
  2. 这里有个问题,由于set句在前,数据包进入是先计入列表,再判定是否合法。这导致第5个包到达后,先在列表中+1,结果是5,再由规则2判定,发现是5,结果丢弃该包,    最后真正ACCEPT的只有4个包。其实个人认为这样写的代码不符合正常的思维逻辑, 而且这样写只能正常工作于默认策略是ACCEPT的情况,所以不建议用这个版本的命令,我的版本ACCEPT、DROP策略都能用。

从上面可以看出,在使用recent模块的命令的时候,一定要先确认iptables的INPUT链的默认策略是什么。

接着说下--rcheck 和 --update的区别 --rcheck从第1个包开始计算时间,--update是在rcheck的基础上增加了从最近的DROP包开始计算阻断时间,具有准许时间和阻断时间,update会更新last-seen时间戳。

就拿上面那个配置案例来说, rcheck是接收到第1个数据包时开始计时,一个小时内仅限5次连接,后续的包丢弃,直到一小时过后又可以继续连接。update则是接收到第1个数据包时计算准许时间,在一个小时的准许时间内仅限5次连接,当有包被丢弃时,从最近的丢弃包开始计算阻断时间,在一个小时的阻断时间内没有接收到包,才可以继续连接。所以rcheck类似令牌桶,一小时给你5次,用完了抱歉等下个小时吧。update类似网银,连续输错5次密码,停止一小时,只不过update更严格,阻断时间是从最近的一次输错时间开始算,比如输错了5次,过了半个小时又输错一次,这时阻断时间不是剩半小时,而是从第6次重新计算,剩一小时. 

可以拿下面这个命令进行测试, 自行替换rcheck、update,然后ping一下就明白了:

温馨提示: ICMP包和UDP包在iptables中的state情况是一样的,因为是无状态的,不同于TCP,iptables可以靠SYN等flags确定state,而iptables是基于ICMP包/UDP包到达服务器的间隔时间来确定state的。比如在做上面测试的时候,使用ping 192.168.10.10 -t时,除了第一个ICMP包state是NEW,后续的包state都是ESTABLISHED,结果因为前面有一句:

结果测试ping一直是通的,这个一定要弄明白!

3) 限制80端口60秒内每个IP只能发起10个新连接,超过记录日记及丢失数据包,可防CC及非伪造IP的syn flood

以上命令解说

  • 第1行规则表示: 60秒10个新连接,超过记录日志。
  • 第2行规则表示: 60秒10个新连接,超过记录日志。
  • 第3行规则表示: 范围内允许通过。
    即每个IP目标端口为80的新连接会记录在案,可在/proc/net/xt_recent/目录内查看,rcheck检查此IP是否在案及请求次数,如果超过规则就丢弃数据包,否则进入下条规则并更新列表信息。

发送特定指定执行相应操作,按上面设置, 如果自己IP被阻止了,可设置解锁。

4)  默认封闭SSH端口,为您的SSH服务器设置开门暗语

5) 指定端口容易被破解密钥,可以使用ping指定数据包大小为开门钥匙

按照上面配置后, 依然无法ssh登录到指定主机, 因为没有添加"INPUT链的默认策略为ACCEPT"的前提, 即需要下面这个前提条件!

整理后的配置规则

针对上面整理后的配置规则说明

  • 第1,2行规则表示: 清空原有的iptables规则
  • 第3行规则表示: 已经建立成功的连接和与主机发送出去的包相关的数据包都接受,如果没有这一步,后面的tcp连接无法建立起来
  • 第4行规则表示: 出现长度为78字节icmp回响包在/var/log/syslog生成log,log以SSH_OPEN_KEY开头
  • 第5行规则表示: 出现长度为78字节icmp回响包,将源地址信息记录在openssh文件中,并接受
  • 第6行规则表示: 对于openssh文件中的源地址60s以内发送的ssh连接SYN请求予以接受
  • 第7行规则表示: 将INPUT链的默认策略设置为drop

调试过程:

  1. 如果没有设置第3行规则,则无法建立ssh连接
  2. 在没有第3行规则的情况下,设置第6行如果不加--syn,则可以ssh连接一会儿,过一会儿又自动断线,除非ping一下目的地址. 原理是:ping目的地址,则会更新openssh的时间,这样ssh连接还在60s之内,所以可以通信,过一会儿,60s超时,则就会断开ssh连接。如果加了--syn,只能进行开始的syn,无法正常连接

在客户机上,如果需要ssh到主机,需要先ping主机进行解锁

并在一分钟之内ssh到主机,这样在/proc/net/xt_recent/目录下生成openssh文件, 内容如下:

参考链接


Iptables之recent模块小结