DNS服务的部署与配置(2)
1、dns的安装及开启
dnf install bind.x86_64 -y #安装
#Berkeley Internet Name Domain (BIND)
systemctl enable --now named #启用dns服务,服务名称叫named
firewall-cmd --permanent --add-service=dns #火墙设置
firewall-cmd --reload #重启火墙
setenforce 0 #调整内核级火墙为警告模式
2、配置dns服务使内网主机可以访问其dns资源
netstat -antlupe | grep named #可以查看dns开放端口
vim /etc/named.conf #编辑dns配置文件,对文件做以下修改
11行左右 listen-on port 53 { any; }; #在本地所有网络接口上开启53端口
19行左右 allow-query { any; }; #允许查询A记录的客户端列表,提供服务给所有主机
20行左右 forwarders { 114.114.114.114; }; #将源换为国内的,指定资源从114上取,这样速度会快一点
34行左右 dnssec-validation no; #禁用dns检测使dns能够缓存外部信息到本机,开着会因为检测不合规返回不了“答案”
##每一个字符串一定要用分号结尾
systemctl restart named #重启服务


使用内网其他主机测试:
vim /etc/resolv.conf #编辑dns指向文件 nameserver 192.168.187.129
#添加我们配置的dns服务器的ip dig www.baidu.com
#解析测试我们的dns服务器配置是否成功

显示NOERROR就是没有问题!

3、DNS的正向解析
企业内部也需要对外提供dns做相应的解析工作!
准备工作:
在上个高速缓存配置的基础上,先编辑主配置文件vim /etc/named.conf,将源注释掉

然后使用命令nm-connection-editor将dns服务器在的主机和测试主机的ip都改为静态ip
dns服务器的IP改成:192.168.187.129
测试主机IP改为:192.168.187.136


修改配置并保存
(1)主机记录A记录
第一步:添加域名语句块
vim /etc/named.rfc1912.zone
##和主配置文件里的内容一样,里边有要维护域名的语句块
##主配置文件读取域名信息就会到这个文件里读取
##我们可以在这个文件里添加我们要维护的域名的语句块
添加:
zone "lucky.com" IN { #维护的域名
type master; #当前服务器位主dns
file "lucky.com.zone"; #域名A记录文件,要解析域名时看的是这个文件
allow-update { none; }; #允许更新主机列表
};

第二步:编辑域名A记录文件
cd /var/named/ #进入数据目录
cp -p named.localhost lucky.com.zone #复制模板得到我们要的域名A记录文件,一定要加-p参数,所属组相同
vim lucky.com.zone #编辑A记录文件
A记录文件内容及解释如下:
$TTL 1D #TIME-TO-LIVE(dns地址保存时间长度)
@ IN SOA dns.lucky.com. root.lucky.com ( #SOA授权起始(Start of Authority),谁授权的
#@符的值就是/etc/named.rfc1912.zone文件里我们编写的域名语句块引号里的内容
#不是以.结尾的字符串都会被自动补齐@符的值
0 ; serial #域名版本序列号,下文dns集群会用到,有详细解释
1D ; refresh #刷新时间(辅助dns)
1H ; retry #重试时间(辅助dns)
1W ; expire #过期时间(辅助dns,查询失败过期停止对辅助域名的应答)
3H ) ; minimum #A记录最短有效期
NS dns.lucky.com.
dns A 192.168.187.129
lucky.a A 192.168.187.97 ##正向解析记录
lucky.a A 192.168.187.99
复制并编辑A记录文件


第三步:重启并在另一台内网主机测试systemctl restart named
另一台主机先检查下dns服务器是不是我们设置的

然后dig www.lucky.com,如图测试成功!
##多个ip会自动做轮调

(2)规范域名转换CNAME记录
当内部主机名不规范时,对外开放的是规范域名。
那么对外开放的域名只有一个,将对外开放的域名转换到内部主机再做解析
dns服务器端:
vim /var/named/lucky.com.zone #编辑A记录文件
添加:
www CNAME www.a.lucky.com.
#www.a.lucky.com.就是不规范域名
systemctl restart named #重启dns
客户端:
dig www.lucky.com #另一台主机测试
编辑文件

重启

另一台主机测试,如图设置成功!

(3)邮件解析MX记录
什么是MX记录?
当我们在发送邮件时,假设我们用的163.com邮箱,需要将163.com解析成ip才能进行数据传输,这个ip就叫这个域的mx记录(负责邮件发送和接收的ip)。
dns服务器端
vim /var/named/lucky.com.zone
#编辑A记录文件 添加后保存退出:
lucky.com. MX 1 192.168.187.129.
systemctl restart named
#重启dns
添加时写的是服务器ip

客户端:
dnf install postfix mailx -y #安装提供邮件投递协议的软件postfix和发送邮件的客户端mailx systemctl start postfix #开启postfix服务
dig -t mx lucky.com #查看mx记录
查看mx记录,没有问题

发邮件给root@lucky.com(自行类比@qq.com)
##因为在dns服务器端25端口是自用的(回环),所以不会收到邮件,所以我们在测试端看发送队列看下效果即可
##如图即是正向解析成功

4、DNS的反向解析
逆向查询记录PTR记录
什么是PTR记录?
邮件接收方只会显示发送方的ip,需要做反向解析,显示真实的域名,让用户知道邮件从哪儿来的。从ip到域名就是ptr记录。
dns服务器端
vim /etc/named.rfc1912.zones #编辑文件
添加:
zone "187.168.192.in-addr.arpa" IN {
type master;
file "192.168.187.ptr";
allow-update { none; };
};
cd /var/named/
cp -p named.loopback 192.168.187.ptr #复制模板得到ptr文件
vim 192.168.187.ptr #编辑ptr记录文件
修改成下文:
$TTL 1D
@ IN SOA dns.lucky.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns.lucky.com.
dns A 192.168.187.129
233 PTR www.lucky.com.
#反向解析IP192.168.187.233应该得到域名www.lucky.com
systemctl restart named #重启
编辑named.rfc1912.zones文件

编辑ptr记录文件

客户端:dig -x 192.168.187.233测试如图成功!

5、DNS的双向解析
双向解析:
在内网中的主机解析得到内网的ip,
在外网中的主机解析得到外网的ip。
实验环境:
我们需要一台双网卡主机模拟内网,一台单网卡主机模拟外网
dns服务器端做内网主机:
添加一个网卡,将ip设为192.168.0.0/24网段的
原来的192.168.187.0/24网段的做内网ip

单网卡主机做外网主机:
ip改为192.168.0.0/24网段的,模拟外网主机,并且将网关设为dns服务器端192.168.0.0/24网段的ip,保证两台主机能相互通信

两台主机更改完网络后都需重启网络
nmcli connection reload
nmcli connection up
网络名 例如客户端网卡名为ens160,那么就是
nmcli connection up ens160
设置完后ping一下通了即可

dns服务器端(内网主机):
vim /etc/named.conf #编辑主配置文件
将下图内容注释掉:

注释掉后,在下边添加如下内容:
view localnet {
match-clients { 192.168.187.0/24; };
zone "." IN {
type hint;
file "named.ca";
};
include "/etc/named.rfc1912.zones";
};
view internet {
match-clients { any; };
zone "." IN {
type hint;
file "named.ca";
};
include "/etc/named.rfc1912.zones.inter";
};

拷贝/etc/named.rfc1912.zones文件得到/etc/named.rfc1912.zones.inter文件
cp -p /etc/named.rfc1912.zones /etc/named.rfc1912.zones.inter
vim /etc/named.rfc1912.zones.inter #编辑外网配置文件
做如下图更改:

拷贝A记录文件得到外网的A记录文件
cp -p /var/named/lucky.com.zone /var/named/lucky.com.inter
vim /var/named/lucky.com.inter #编辑外网A记录文件
做如下图更改:
#把ip都改成我们想让外网主机访问时看到的ip

重启systemctl restart named
vim /etc/resolv.conf #添加dns服务器
ip nameserver 192.168.187.129
#因为更改过网络,所以可能需要重新添加

客户端(外网主机)
vim /etc/resolv.conf #添加dns服务器
ip nameserver 192.168.187.129 #因为更改过网络,所以可能需要重新添加

测试:
dns服务器端(内网主机):
dig -x 192.168.187.233测试,如图显示的内网ip,成功!

客户端(外网主机):dig -x 192.168.187.233测试,如图显示的外网ip,成功!

6、DNS集群
当我们的主dns服务器访问量过大时,服务器不足以支撑这么大的访问量,我们可以增加n台辅助dns来分担访问压力。
我们下面以增加一台辅助dns来实验如何使主辅dns同步更新!
辅助dns:
我以上面用过的客户端主机为辅助dns
先将其IP改为和主dns一个网段的,192.168.187.136

更改完网络后需重启网络
nmcli connection reload
nmcli connection up ens160
dnf install bind.x86_64 -y #也安装dns
#Berkeley Internet Name Domain (BIND)
systemctl enable --now named #启用dns服务,服务名称叫named
firewall-cmd --permanent --add-service=dns #火墙设置
firewall-cmd --reload #重启火墙
setenforce 0 #调整内核级火墙为警告模式
vim /etc/named.conf #编辑主配置文件
注释掉11,12,19行
vim /etc/named.rfc1912.zones #在文件中加入域名语句块
添加:
zone "lucky.com" IN {
type slave; #类型是辅助dns
masters { 192.168.187.129; }; #主dns
file "slaves/lucky.com.zone"; #数据同步到slaves目录下
};
编辑主配置文件注释掉如图三行,就相当于全部都开启(any)

添加域名语句块

vim /etc/resolv.conf
nameserver 192.168.187.136 #将dns服务器改为自己的,为了看效果
systemctl restart named #重启dns服务

主dns:
我以上面配好的dns服务器192.168.187.129这台主机为主dns
先去掉上个实验的配置,防止影响
vim /etc/named.conf
#编辑主配置文件
注释掉如下图内容:

vim /etc/named.rfc1912.zones
在域名语句块内添加如下内容:
also-notify { 192.168.187.136; }; #辅助dns的ip
systemctl restart named #重启dns

测试:
辅助dns:
dig www.lucky.com得到如图结果:

主dns:
vim /var/named/lucky.com.zone
#编辑A记录文件 更改下ip和serial值:
之后在辅助dns端重新dig看是否同步成功

serial值的作用:
每更改一次该值并重启主dns服务后,辅助dns就会重新同步A记录
即重新同步域名所对应ip
一天可以改99次
值可以任意写!
!!!!!但只能增量更改!!!!!
其他值解释:
1D ; refresh #刷新时间(辅助dns)
1H ; retry #重试时间(辅助dns)
1W ; expire #过期时间(辅助dns,查询失败过期停止对辅助域名的应答)
3H ) ; minimum #A记录最短有效期
辅助dns:dig www.lucky.com得到如图结果:
测试成功!ip同步成功!

DNS(DHCP+DNS)动态域名解析
dhcp能自动分配ip,当重新分配时怎么让dns知道ip重新分配了呢?ddns可以解决这个问题,实现动态域名解析。
更新原理:制作一个key,让dhcp能更新dns的A记录,key是更新域名的钥匙。
在/var/named目录下生成一个更新数据,在系统读取A记录时会把.jnl结尾的更新文件与A记录文件整合实现。
ddns服务端
dnf install dhcp-server -y #安装dhcp服务器
cp /usr/share/doc/dhcp-server/dhcpd.conf.example /etc/dhcp/dhcpd.conf #复制模板得到配置文件
vim /etc/dhcpd/dhcpd.conf #编辑dhcp配置文件
做如下图修改:
#修改最终结果是剩31行

systemctl start dhcpd #开启dhcp
接下来制作更新域的“钥匙”key:
#/etc/rndc.key是dns默认使用的key模板,用的是SHA-256加密,所以我们下面也要使用SHA-256加密
cd /mnt/
dnssec-keygen -a HMAC-SHA256 -b 128 -n HOST luckykey
#SHA256加密方式是对称的,公钥和私钥是一样的

cp -p /etc/rndc.key /etc/lucky.key #复制key模板得到key文件
vim /etc/lucky.key #编辑key文件
改成如下内容:
key "luckykey" { #我们前面取的key名字
algorithm hmac-sha256; #加密方式
secret "/P/GVMVRb/dNIjtr2qYvMg=="; #我们前面生成的密钥,最好复制粘贴
};

vim /etc/named.conf #更改dns主配置文件加key文件指向
在第45行左右添加key文件指向:
include "/etc/lucky.key";

vim /etc/named.rfc1912.zones #域名语句块在这里
在域名语句块里添加key更新:
如下图:

systemctl restart named #重启dns
接下来测试一下该key能否更新dns:
nsupdate -k Kluckykey.+163+37031.private #-k指定key,不指定send会失败
> update add hello.lucky.com 86400 A 192.168.187.111 #新增A记录
> send #成功
> update del hello.lucky.com #删除A记录
> send #成功
> quit #退出
测试成功!继续下一步

vim /etc/dhcp/dhcpd.conf #编辑dncp配置文件
打开dns更新的“开关”:
第14行取消注释,并改为interim(网络更新):
ddns-update-style interim;
在最后指定key,相当于让dhcp拿到了dns更新的“钥匙”:
key luckykey { #我们前面取得key的名字,别写错了
algorithm hmac-sha256;
secret /P/GVMVRb/dNIjtr2qYvMg==; #最好直接复制前面我们生成的key文件里的防止出错
};
在最后加入key要更新的域:
zone lucky.com. {
primary 127.0.0.1; #dns在本机,所以直接写本机回环接口就可以了
key luckykey; #我们前面取得key的名字,别写错了
}

删掉jnl文件(不然前面的更新测试会影响):
rm -fr /var/named/lucky.com.zone.jnl
重启两个服务:
systemctl restart dhcpd
systemctl restart named

客户端:
首先要关闭VM虚拟机的本地dhcp服务,如下图操作即可:
##如果是真机是linux系统直接在虚拟机里改配置文件即可

选择更改设置

取消勾选本地dhcp服务

然后将我们之前设置的静态ip改为dhcp:
nm-connection-editor

测试下我们是否关闭本地dhcp成功:
nmcli connection up ens160 #重启网卡
cat /etc/resolv.conf #看下dns服务用的谁的
如图是用的我们自己配置的,设置成功!

改下主机名方便测试:
hostnamectl #查看主机名
hostnamectl set-hostname nodeb.lucky.com #改主机名为nodeb.lucky.com

测试:
客户端:
dig nodeb.lucky.com
ifconfig 看两个出来的ip一样否
如图是一样的

dns服务端:
vim /etc/dhcp/dhcpd.conf #编辑dncp配置文件
改一下ip范围:
我改为了77-90,如下图:

重启下dhcp服务: systemctl restart dhcpd

客户端
nmcli connection up ens160 #重启网卡,
那么会重新获取ip
dig nodeb.lucky.com
ifconfig 看两个出来的ip一样否
如图,重新获取的ip是我们上面重新设置的范围内的,dns解析也是同步的

测试成功!
相关文章:
DNS服务的部署与配置(2)
1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务,服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …...
MySql--SQL语言
目录 SQl---DDL 结构定义 创建、删除 数据库 代码 运行 设计表 数据类型 整数 浮点数 主键 约束 主键自增长 默认值 字段注释 创建、删除 表 代码 运行 代码 代码 运行 SQL---DML 数据操纵 插入数据 代码 运行 代码 运行 代码 运行 代码 …...
【网络安全】2030年十大新兴网络安全威胁
欧盟网络安全局(ENISA)已发布了一份全面的清单,列出了预计到2030年将影响数字领域的十大新兴网络安全威胁。 该预测是为期八个月的广泛研究的成果,融合了ENISA前瞻专家小组、CSIRTs网络以及欧盟CyCLONe专家的见解。 这项研究突显…...
python数据分析-CO2排放分析
导入所需要的package import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import datetime %matplotlib inline plt.rcParams[font.sans-serif] [KaiTi] #中文 plt.rcParams[axes.unicode_minus] False #负号 数据清洗…...
2024宝藏工具EasyRecovery数据恢复软件免费版本下载
在这个数字化的时代,数据已经成为我们生活中的重中之重。无论是工作中的重要文件,还是手机中珍贵的照片,我们都依赖着这些数据。然而,数据丢失的情况时有发生,可能是误删,可能是设备故障,更可能…...
【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次,并且数据被合并
【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次,并且数据被合并 出错描述 出错原因与解决方案 出错描述 SSE前后端一切正常,但是fetchEventSource 的onmessage回调函数只在所有流都发送完毕后,才会执行一次。 前…...
如何在linux命令行(终端)执行ipynb 文件。可以不依赖jupyter
1.安装 runipy pip install runipy 2.终端运行 runipy <YourNotebookName>.ipynb 在终端命令行执行shell脚本,(也可以在crontab 中执行): (base) [recommendapp-0-5-B-006 script]$ cat run1.sh #!/bin/bashcd /home/recom…...
基于YOLOv8的车牌检测与识别(CCPD2020数据集)
前言 本篇博客主要记录在autodl服务器中基于yolov8实现车牌检测与识别,以下记录实现全过程~ yolov8源码:GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite 一、环境配置 …...
驱动开发之新字符设备驱动开发
1.前言 register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数,现在新的 字符设备驱动已经不再使用这两个函数,而是使用 Linux 内核推荐的新字符设备驱动 API 函数。 旧版本的接口使用,感兴趣可以看下面这个博客&#…...
【JMU】21编译原理期末笔记
本拖延症晚期患者不知不觉已经有半年没写博客了,天天不知道在忙什么。 乘着期末周前赶紧先把编译原理上传了,我记得我这科是86分,有点小遗憾没上90,但是总体不错。 链接:https://pan.baidu.com/s/1gO8pT7paHv1lkM_ZpkI…...
就业信息|基于SprinBoot+vue的就业信息管理系统(源码+数据库+文档)
就业信息管理系统 目录 基于SprinBootvue的就业信息管理系统 一、前言 二、系统设计 三、系统功能设计 1前台功能模块 2后台功能模块 4.2.1管理员功能 4.2.2学生功能 4.2.3企业功能 4.2.4导师功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…...
一.架构设计
架构采用 ddd 架构,不同于传统简单的三层的架构,其分层的思想对于大家日后都是很有好处的,会给大家的思想层级,提高很多。 传统的项目 现有的架构 采取ddd架构,给大家在复杂基础上简化保留精髓,一步步进行…...
<学习笔记>从零开始自学Python-之-实用库篇(一)-pyscript
由Anaconda创建的PyScript是一项实验性的但很有前途的新技术,它使python运转时在支撑WebAssembly的浏览器中作为一种脚本言语运用。 每个现代常用的浏览器现在都支撑WebAssembly,这是许多言语(如C、C和Rust)能够编译的高速运转时…...
Vue项目中npm run build 卡住不执行的几种情况(实战版)
方法一 一:比较常见是镜像导致的原因 我们可以找到build/check-versions文件 将这段代码注释,重新运行就可以解决这个问题 if (shell.which(npm)) {versionRequirements.push({name: npm,currentVersion: exec(npm --version),versionRequirement: packageConfig.en…...
《Python源码剖析》之pyc文件
前言 前面我们主要围绕pyObject和pyTypeObject聊完了python的内建对象部分,现在我们将开启新的篇章—python虚拟机,将聚焦在python的执行部分,搞懂从“代码”到“执行”的过程。开启新的篇章之前,你也许会有一个疑惑:我…...
Python零基础-中【详细】
接上篇继续: Python零基础-上【详细】-CSDN博客 目录 十、函数式编程 1、匿名函数lambda表达式 (1)匿名函数理解 (2)lambda表达式的基本格式 (3)lambda表达式的使用场景 (4&…...
回溯 leetcode
22. 括号生成 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:["((()))","(()())","(())()","()(())"…...
Android firebase消息推送集成 FCM消息处理
FirebaseMessagingService 是 Firebase Cloud Messaging (FCM) 提供的一个服务,用于处理来自 Firebase 服务器的消息。它有几个关键的方法,你提到的 onMessageReceived、doRemoteMessage 和 handleIntent 各有不同的用途。下面逐一解释这些方法的作用和用…...
react中怎么为props设置默认值
在React中,你可以使用ES6的类属性(class properties)或者函数组件中的默认参数(default parameters)来定义props的默认值。 1.类组件中定义默认props 对于类组件,你可以在组件内部使用defaultProps属性来…...
企业如何做好 SQL 质量管理?
研发人员写 SQL 操作数据库想必一定是一类基础且常见的工作内容。如何避免 “问题” SQL 流转到生产环境,保证数据质量?这值得被研发/DBA/运维所重视。 什么是 SQL 问题? 对于研发人员来说,在日常工作中,大部分都需要…...
012-java精品项目-淘客系统源码(安卓+IOS+php后端)
本文介绍了一个完整的淘宝客App开发项目,包含Android端、iOS端、后端服务和数据库系统。项目提供了详细的接口文档(淘宝客App接口文档.doc)和客户申请资料(淘宝客客户需要申请资料.doc),并包含完整的淘宝客…...
Windows 批量解压 TAR 文件脚本:支持文件数量校验、断点续解压和自动跳过
文章目录一、需求说明二、脚本功能三、为什么使用 7-Zip1. 7-Zip 支持命令行调用2. 方便读取 tar 包内部文件列表3. 支持跳过已存在文件,适合断点续解压4. 对 tar 文件支持比较稳定5. 适合处理大量小文件场景四、完整 BAT 脚本五、使用前需要修改的地方六、脚本运行…...
2026最新免费在线去水印工具详细教程,在线去本地视频水印保姆级指南
你是不是也遇到过这种情况?辛辛苦苦在网上找到一个绝美视频素材想用在剪辑里,结果画面正中央横着一个硕大的水印;或者刷小红书看到一段干货满满的教学视频,想保存下来反复学习,却被角落的Logo劝退。更头疼的是…...
蛋白质设计新范式:QUBO建模与迭代学习框架解析
1. 项目概述与核心思路在生物信息学和计算生物学领域,蛋白质设计一直是一个“圣杯”级别的挑战。简单来说,它要回答一个逆向问题:给定一个我们想要的蛋白质三维结构,如何从头设计出能折叠成这个结构的氨基酸序列?传统方…...
如何利用AI工具变现:一个老程序员的真实观察
凌晨两点,你又刷到一个"AI月入5万"的短视频。 关了手机,睡不着了。 明天还要上班。 这种焦虑感,我太熟悉了。 作为一个写了12年代码的老程序员,这两年被问到最多的问题就是:"有什么真正能用的AI变现方法?" 今天不画饼,说点真话。 先说结论 AI…...
HashMap 源码解析 底层原理 面试如何回答
HashMap 源码解析 底层原理 面试如何回答 一、参考资料 【Java视频教程,java入门神器(附300道Java面试题剖析)】 https://www.bilibili.com/video/BV1PY411e7J6/?p172&share_sourcecopy_web&vd_source855891859b2dc554eace9de3f28b4…...
企业级多模型聚合平台选型,如何通过用量看板实现成本精细化管理
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业级多模型聚合平台选型,如何通过用量看板实现成本精细化管理 当企业技术团队决定将大模型能力深度融入业务流程时&a…...
ChatGPT移动端隐私红线报告(2024Q2):麦克风/剪贴板/位置数据采集路径全曝光,3步彻底锁死敏感权限
更多请点击: https://intelliparadigm.com 第一章:ChatGPT移动端隐私红线报告(2024Q2)核心发现与风险定级 高危数据外泄通道实证 本季度对iOS与Android平台主流ChatGPT客户端(含官方App v6.12.1及第三方封装SDK集成应…...
Loop:终极免费开源Mac窗口管理工具,彻底解决桌面杂乱问题
Loop:终极免费开源Mac窗口管理工具,彻底解决桌面杂乱问题 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你是否曾经因为Mac上杂乱的窗口布局而效率低下?当多个应用同…...
