Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

很早之前就有用过iptables,那时候是早期版本的Ubuntu系统,配置防火墙的时候,是挺复杂的,就是在reject之前添加accept规则,并且当时很多网上资料都是在后续添加就行,这个其实在当时是有问题的,所以比较印象深刻。
这次碰到的问题是对iptables的概念不熟悉有关,因为iptables的逻辑其实也有一定问题我觉得,比如最基本的命令,iptables -L
这里help显示的是会展示所有chain的rules

但是这样完全把table概念给忽略了,如果不注明理论上应该把所有table的展示出来,或者把包含这个参数并且是默认给出filter这个table的写清楚
所以这次要补一下这部分概念
iptables里首先就是有四种table,分别是 Filter, NAT, Mangle, Raw四种内建表
并且层次结构是 iptables -> Tables -> Chains -> Rules.
filter:
This is the default table (if no -t option is passed). It contains the built-in chains INPUT (for packets destined to local sockets), FORWARD (for packets being routed through the box), and OUTPUT (for locally-generated packets).
包含 INPUT,FORWORD和OUPUT三个chain,默认就是展示这个,所以就会导致用iptables -L 显示不了mangle table的规则
nat:
This table is consulted when a packet that creates a new connection is encountered. It consists of three built-ins: PREROUTING (for altering packets as soon as they come in), OUTPUT (for altering locally-generated packets before routing), and POSTROUTING (for altering packets as they are about to go out).
nat包含 PREROUTING,OUTPUT,POSTROUTING三个chain
mangle:
This table is used for specialized packet alteration. Until kernel 2.4.17 it had two built-in chains: PREROUTING (for altering incoming packets before routing) and OUTPUT (for altering locally-generated packets before routing). Since kernel 2.4.18, three other built-in chains are also supported: INPUT (for packets coming into the box itself), FORWARD (for altering packets being routed through the box), and POSTROUTING (for altering packets as they are about to go out).
mangle主要用于专门的数据包更改,包含 PREROUTING,INPUT,OUTPUT,FORWARD,POSTROUTING 五个chain,注意有内核版本区别,只是现在基本没那么老的内核了
raw:
This table is used mainly for configuring exemptions from connection tracking in combination with the NOTRACK target. It registers at the netfilter hooks with higher priority and is thus called before ip_conntrack, or any other IP tables. It provides the following built-in chains: PREROUTING (for packets arriving via any network interface) OUTPUT (for packets generated by local processes)
包含 PREROUTING和OUTPUT,主要用来配置例外
chain内部会有实际的rule规则,这个具体后面可以介绍

玩客云 casaos

玩客云这样的小机器现在也有一些自己的生态了,感谢开源大佬们的贡献,这个casaos就是个颜值颇高的轻nas方案,casaos虽然叫做os,但其实一套轻nas组件,并且有一个好看的webui,然后通过docker来作为内部的软件市场安装形式,我们沿着上一篇接下来尝试下安装轻度试用下这个casaos,首先安装

1
2
3

curl -fsSL https://get.casaos.io | sudo bash

安装会提示空间不够大,可以先忽略,如果想更保险的话就可以通过加一张SD卡或者USB插外接硬盘

安装中主要是执行了casaos的一些安装shell,以及启动rclone服务,完成后给出了登录地址,默认是80端口,可以在后面UI界面里更改端口


也可以设置自动挂载usb

安装完以后打开地址

创建账户

进入系统后的UI长这样


还是挺赏心悦目的,默认会展示系统的状态,cpu,内存和存储网络这些,预装了syncthing作为同步工具,还有个App Store

有挺多应用在商店

只是这里就会发现个问题,只是玩客云是32为的ArmV7系统

有很多组件不支持,包括jellyfin这些,不过它提供了自定义安装功能,可以自定义安装docker镜像

不过这里有个小bug,拷贝镜像名进入第一个输入框以后会提示不能为空,这边需要带上tag一起复制进去

第二个问题是我安装的0.4.8是没办法安装latest以外的tag的,不然会提示 store app not found

在dockerhub上是有armv7版本的jellyfin的,只是没有latest这个tag的,如果实在想体验下就考虑安装casaos的0.4.7或更早先版本的或者可以自己在Armbian里拉取镜像再安装下Portainer来管理docker,不过玩客云的性能是真的很羸弱,所以不要抱什么期望,低负载的任务可以跑跑,jellyfin显然不是很合适的,只是作为一个示例

逻辑复杂负载比较高的就算了,考虑N1或者其他性能更好的机器

LlamaIndex 是目前比较新的大模型RAG框架,RAG是指 检索增强生成 (Retrieval-Augmented Generation, RAG)是指在利用大语言模型回答问题之前,先从外部知识库检索相关信息。RAG 被证明能显著提升答案的准确性,并特别是在知识密集型任务上减少模型的错误输出。通过引用信息来源,用户可以核实答案的准确性,从而增强对模型输出的信任。
此外,RAG 有助于快速更新知识并引入特定领域的专业知识。
RAG 有效结合了大语言模型的参数化知识和非参数化的外部知识库,成为实施大语言模型的关键方法之一。本文概述了 RAG 在大语言模型时代的发展模式,总结了三种模式:初级 RAG、高级 RAG 和模块化 RAG。
首先我们可以了解下LlamaIndex的几大模块,
使用大型语言模型(LLMs):无论是OpenAI还是任何托管的LLM,亦或是您自己本地运行的模型,LLM都被用于从索引和存储到查询和解析数据的每一个步骤。LlamaIndex提供了大量可靠经过测试的提示,我们也将向您展示如何自定义您自己的提示。
LlamaIndex 主要有这五大块能力

  • Data connectors
  • Data indexes
  • Engines
  • Data agents
  • Application integrations

其中加载部分可以认为是初始的部分,我们可以从各个数据源去获取信息,比如各种文档,或者confluence,甚至api接口,只需要合适的数据加载器,我们就能将其转化为我们要的数据
比如我想要将我博客里的Markdown文件作为知识库加载

1
2
3
4
5
6
reader = SimpleDirectoryReader(
input_dir="./somedir/source/_posts/",
required_exts=[".md"],
recursive=True
)
docs = reader.load_data()

然后由文档来就构建我们的索引

1
index = VectorStoreIndex.from_documents(docs)

但是这里我们需要提前设置好对应的 embedding 模型,这个很重要,如果有条件推荐使用OpenAI的,如果想用本地的可以考虑使用BAAI智源出品的,只是要注意是否支持多语言,如果要使用本地embedding的话需要安装

1
pip install llama-index-embeddings-huggingface

这里我选了BAAI也就是智源研究所的bge-m3模型,因为这个是支持多语言的,如果是纯英文的可以用他们 BAAI/bge-small-en-v1.5

1
2
3
4
5
6
7
8
9
10
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
Settings.llm = Ollama(model="gemma:7b", request_timeout=60.0)
Settings.embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-m3"
)
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(llm=gemma_7b)
response = query_engine.query("数据库主从延迟")
print(response)

另外LLM 我使用了本地部署的 gemma:7b,因为想尝试下本地的链路,需要注意的是一些文档还是用的原来的service_context,在新版本中这个已经被改掉了,都是通过 Settings 来设置,此外还有诸如 SimpleDirectoryReader 这些包也被挪到了 llama_index.core 中,需要注意下
然后我们就能使用这种方式来增强LLM,把我们的本地文档作为知识库来搜索,结合了大模型的能力。

derper是 tailscale 已经开源的 tailscale 中转服务,可以进行自己搭建,不然就是使用 tailscale 提供的 derper 节点,我的体验是在晚上高峰期会比较卡,所以有能力可以自建的话也是比较推荐的,不过相对比前面的设置会麻烦点

第一个就是默认这个是需要 https 的,所以需要给 derper 服务申请个域名,或者有了域名就加个解析,比如 dp.hello.com,申请完域名就需要申请证书了,这个刚好就学习下使用 acme.sh这个工具,还是非常不错的,我用的是腾讯云的域名解析服务,其实是收购的 dnspod 的服务,acme.sh 安装就很简单,一条命令

`

1
curl  https://get.acme.sh | sh

然后成功了之后就要把.zshrc 生效下,默认会把脚本路径加入到当前的 shell 的 rc 文件里,然后就是申请证书,但是有两种方式,一种就是在域名指定的 ip 机器对应的访问路径下放置验证的文件

1
acme.sh  --issue  -d domain.tld -d www.domain.tld  --webroot  /home/wwwroot/domain.tld/

比如这样指定 webroot,另一个中更方便的方式就是通过 dns 认证的方式,我这边以 dnspod 举例,这边要特别注意的是 dnspod 虽然被腾讯云收购,但是这个方式还是需要用 dnspod 原来自己的 api token 验证的

然后拿到生成的 id 跟 token 设置到环境变量里,需要保存好这个 token,后面是看不到了的

1
2
export DP_Id=123456
export DP_Key=xxxxxx

然后就可以用命令进行验证了

1
acme.sh --issue --dns dns_dp -d xxx.hello.com

这个是 dnspod 家的,其他的也可以在这里找到验证方式

申请完成后会把证书放在用户目录下的.acme.sh 目录中,记得把cer文件改成 crt,并且文件名只能是域名 xxx.hello.com.crt,我没试过其他的行不行,从别的文章里看到需要一致,然后就是启动 derper 了

我们通过 docker 的方式,

1
2
3
4
5
6
7
8
9
sudo docker run --restart always \
--name derper -p 12345:12345 -p 3478:3478/udp \
-v /$dir/.acme.sh/xxxxx.hello.com_ecc/:/app/certs \
-v /run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \
-e DERP_CERT_MODE=manual \
-e DERP_ADDR=:12345 \
-e DERP_DOMAIN=xxxxx.hello.com \
-e DERP_VERIFY_CLIENTS=true \
-d ghcr.io/yangchuansheng/derper:latest

 前一个端口 12345可以自己随意定,后面$dir改成自己的.acme.sh目录所在的路径,然后

-v /run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \ 这一行 和-e DERP_VERIFY_CLIENTS=true \ 是为了能够让 derper 能够安全一些,就是在本机开一个 tailscale 客户端,连接接到 headscale 服务,可以参考前面的添加节点,然后把这个启动客户端的进程映射进docker里面,因为本身 derper 就没有特别的认证逻辑,所以就让同一个headscale服务的客户端进程来验证是属于同一个headscale服务的节点才允许加入中转,实际这样就跑起来了一个 derper 服务这样可以用 docker 命令查看日志

sudo docker logs -f derper 查看是不是有问题,然后如果没有问题的话还不一定代表 derper 起来了,比较直接的方法就是直接打开域名加上端口的地址,比如 xxxx.hello.com:12345 这个,

image

显示这个就代表服务已经正常启动运行了,然后就是需要修改 headscale 的配置文件了,首先要设置 derper 的配置文件,类似这样

1
2
3
4
5
6
7
8
9
10
11
12
13
regions:
100:
regionid: 100
regioncode: ahk
regionname: Aliyun Hongkong
nodes:
- name: 100a
regionid: 100
hostname: xxxxx.hello.com
ipv4:
stunport: 3478
stunonly: false
derpport: 12345

regionid表示区域 id,一个区域下可以后多个 node,node的 name 是节点的唯一识别码,ipv4 可以不填,有 hostname 就可以,然后stunonly 是 false 表示不只使用 stun还可以使用 derp

然后就是修改 headscale 自身的配置文件,把共用的 derper 配置改成

image

上面的 urls 注释掉,后面的 paths 添加刚才的配置文件路径,这样就可以了,至于连接是不是走的这个

可以用 tailscale netcheck 查看最近的 derper 节点已经延迟,看到使用了自己的 derper 就对了

headscale 在前面两篇初体验添加节点 主要是介绍了如何搭建和使用,但是这里有个很大的缺点,比如我在想要两地的网络能够连通,但是两地的网络内都不止一个机器,那想让他们连通就需要把它们都加入这个 headscale 所组成的虚拟局域网,并且每个都是这个虚拟局域网的ip,跟原来的 ip 地址不一样会比较难记忆,所以有没有办法不用这么麻烦呢,当然是有的,那就是 headscale 的路由功能。
原先比如我们有两个设备,在两地,通过headscale我把这两个异地节点都添加进去了,节点 A 的 ip比如是 10.0.0.1,另一个节点 B 是 10.0.0.2,在之前的状态下,我的节点 A 只能通过 10.0.0.2 来连接节点 B,如果节点 A 想要连接节点 B 所在地的局域网内部其他节点,我们就可以通过节点 B 的客户端登录的时候开启路由转发,这样节点 B 就会充当一个路由转发的功能,并且不需要通过10.0.0这个网段来访问,直接可以通过节点 B所在的局域网地址来访问,比如192.168.2.10,具体操作就是把客户端启动方式改成命令行的,主要就是 --advertise-routes, 指明需要转发的网段

1
tailscale up --advertise-routes=192.168.xx.0/24 --accept-dns=false --login-server=http://serverIp:serverPort --unattended  

前面的 192.168.xx.0 就是节点 B 所在局域网的网段,然后 login-serverheadscale 的服务 ip 跟端口,这个本身客户端就会使用,另外这个还有一个前提的,需要开启服务器的端口转发,对于 Windows 其实默认就可以,Linux 的话就需要设置下

1
2
3
$ echo 'net.ipv4.ip_forward = 1' | tee /etc/sysctl.d/ipforwarding.conf
$ echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/ipforwarding.conf
$ sysctl -p /etc/sysctl.d/ipforwarding.conf

到这里我们只完成了第一步,第二步需要在 headscale 服务端启用这条路由配置
首先可以用 sudo headscale routes 查看当前有的路由
sudo headscale routes enable -h 这里看下怎么启用,因为网上有些是用-i 指定哪一条路由的,但是我使用的这个版本是用-r 的
sudo headscale routes enable -r 1 然后用这个命令启用就行了


这样我们就能够很方便地在单个节点互连之后访问到对方局域网内的其他节点

0%