幻想仙境
2021-04-22幻想仙境是一片快乐的大陆,大家无忧无虑过着快乐的生活。
恋恋在幻想仙境里面,名义是 梦前菜菜。之前的名义 Nanahira 也在用,互不影响。
但是推上面的话,Nanahira 这个名义可能会有版权问题,所以呢就用了幻想仙境的名义 梦前菜菜 作为自己的主要名义。
多条宽带的分流
2020-09-11又好久没有写文章了,想起来写一篇。
最近组网,发现有些场景下,这个地方有多条宽带,然后需要充分利用这么多宽带,用来优化上网体验或是提供更多的对外服务。于是就需要一个可以分流的方案,把入站流量以及出站流量分到不同的宽带里面,充分利用这些宽带的上行或者下行优势。
经过这一段时间的研究,算是研究出来了几种可行的方案,这里列举一下。本文默认内网 IP 段为 10.0.0.0/24。
PPPoE 多拨
这里顺便提供一下 PPPoE 多拨在 Linux 下的正确姿势。PPPoE 多拨需要有不同的 MAC 地址才能拨号。因此我们这里用 macvlan 模拟多个 MAC 地址进行拨号。这种方法不需要添加物理交换机,从墙上或者光猫直接插网线就行。
这里以 Debian 为例,在 /etc/network/interfaces 这样写即可。这里假设 PPPoE 所在的物理网卡为 ens3,只拨 2 个号。如果有 VLAN 的话,可以写成 ens3.10 这样的形式。
auto ens3
iface ens3 inet manual
auto ppp0
iface ppp0 inet ppp
pre-up /bin/ip link add link ens3 dev pppm0 type macvlan && /bin/ip link set pppm0 up
post-down /bin/ip link del dev pppm0
provider ppp0
auto ppp1
iface ppp1 inet ppp
pre-up /bin/ip link add link ens3 dev pppm1 type macvlan && /bin/ip link set pppm1 up
post-down /bin/ip link del dev pppm1
provider ppp1
然后创建 /etc/ppp/peers/pppX 文件(X为ppp编号,从0开始排多个),如下。记得自行更换 ppp0 以及 pppm0 为其他数字。
noipdefault
hide-password
noauth
persist
plugin rp-pppoe.so pppm0
ifname ppp0
user "宽带帐号"
然后在 /etc/ppp/pap-secrets 和 /etc/ppp/chap-secrets 各添加一行宽带帐号信息。
"宽带帐号" * "宽带密码"
需要注意的是,Ubuntu 的 netplan 是不可以拨 PPPoE 的,不过可以把 ifupdown 装回来,就可以如同 Debian 那样配置了。在这种情况下,只需要在/etc/network/interfaces 写和 PPPoE 的虚拟网卡相关的配置就行,物理网卡的启动可以继续放在 netplan 里面。
源进源出
还是从这个古老的话题说起。源进源出之前也研究的很成熟了,尤其是折腾各种 VDIP 和隧道的时候研究的最多的。
先做一个小小的科普,VDIP 这个名词出自 Sakura Frp 之前的附属服务(现在消亡了),全称是 Virtual Dedicated IP Address,给没有公网 IP 的用户提供一条虚拟的公网 IP,并且可以保证用户源 IP。然而这个服务的主人 Akkariin Meiko 也没能悟出这个服务的精髓,即源进源出,即正常的入站流量正常走,而从隧道进来的流量从隧道回去。这里说一个常见的用于 wireguard 的源进源出的命令配置。这里 10.0.1.0/24 为隧道网段。
ipset create mycard hash:net family inet || true
ipset add mycard 10.0.0.0/24 || true
ip rule add pref 80 to 10.0.0.0/24 lookup main || true
ipset add mycard 10.0.1.0/24 || true
ip rule add pref 80 to 10.0.1.0/24 lookup main || true
ip -4 route add 10.0.1.0/24 dev wgmc || true
ip rule add pref 90 fwmark 777 lookup 777 || true
iptables -t mangle -A PREROUTING -i wgmc -m set ! --match-set mycard src -j CONNMARK --set-xmark 777/0xffffffff
iptables -t mangle -A PREROUTING -m connmark --mark 777 -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
iptables -t mangle -A OUTPUT -m connmark --mark 777 -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
上面的 mycard 这个 ipset ,代表全部内网的地址段的 ipset,如果有多个子网或者和隧道连接的其他地方,则都需要写上,ip rule pref 80 lookup main 也是如此。本文后面出现的 mycard ipset 也是这个意思,将不再列举。
这里稍微变通一下,在多宽带的场景下,每条宽带都需要做一个源进源出的规则,然后在 DNS 方面设置一条解析记录,均匀返回两个宽带的 IP,即可完成基本的入站带宽叠加,宽带就有了两倍的对外服务能力。
本人比较习惯于,在 PPPoE 或者其他宽带形式的 PostUp 脚本内,设置 ip rule 和 ip route 规则,而在 wireguard 的 PostUp 脚本内,设置 iptables 规则。这是因为 iptables 会涉及 ipset,而这个 ipset 由于涉及众多节点,只会在wireguard 的脚本内进行添加。
本人使用的 PPPoE 的 PostUp脚本如下,可以参考。
#!/bin/bash
INIT_ID=$[400 + $(echo "$PPP_IFACE" | sed "s/ppp//g")]
INIT_ID_2=$[510 + $(echo "$PPP_IFACE" | sed "s/ppp//g")]
iptables -t mangle -A FORWARD -o "$PPP_IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1452:1460 -j TCPMSS --set-mss 1452
iptables -t mangle -A FORWARD -i "$PPP_IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1452:1460 -j TCPMSS --set-mss 1452
ip6tables -t mangle -A FORWARD -o "$PPP_IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1432:1460 -j TCPMSS --set-mss 1432
ip6tables -t mangle -A FORWARD -i "$PPP_IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1432:1460 -j TCPMSS --set-mss 1432
iptables -t nat -o "$PPP_IFACE" -A POSTROUTING -j MASQUERADE
ip route add default dev "$PPP_IFACE" table $INIT_ID
ip route add default dev "$PPP_IFACE" metric $INIT_ID
ip rule add pref 300 fwmark $INIT_ID lookup $INIT_ID
ip rule add pref 400 fwmark $INIT_ID_2 lookup $INIT_ID
iptables -t mangle -A POSTROUTING -o "$PPP_IFACE" -j TTL --ttl-set 64
iptables -t mangle -A OUTPUT -o "$PPP_IFACE" -j TTL --ttl-set 64
iptables -t mangle -A FORWARD -o "$PPP_IFACE" -j TTL --ttl-set 64
iptables -t mangle -A FORWARD -i "$PPP_IFACE" -j TTL --ttl-set 64
iptables -t mangle -A PREROUTING -i "$PPP_IFACE" -j TTL --ttl-set 64
iptables -t mangle -A INPUT -i "$PPP_IFACE" -j TTL --ttl-set 64
这里简要说明一下,INIT_ID 取值和 pppX 的数值 X 相关,用于批量配置多个 ppp 方便。INIT_ID_2 是另一个辅助 ID。这两个 ID 用于两个不同的 mark。第一个 mark 是用于源进源出的,第二个 mark 是用于分流的。
后 4 行与 mss 相关的规则,是用来协调 PPPoE 的 MTU 的。之后一行是 NAT 。而后面的 ip 开头的命令是用来添加默认路由和策略路由的。这里后面的 iptables 会用到。最后 6 行是用来规范 PPPoE 网卡的数据包的 TTL 的,防止部分运营商通过这个来查到共享上网。
最后是 iptables 部分,放置于 WireGuard 的 PostUp 脚本内,设置源进源出使用的。
ipset create mycard hash:net family inet || true
ipset add mycard 10.0.0.0/24 || true
ip rule add pref 80 to 10.0.0.0/24 lookup main || true
restore_mark() {
OPTION=$1
MARK=$2
iptables -t mangle "$OPTION" PREROUTING -m connmark --mark "$MARK" -j CONNMARK --restore-mark
iptables -t mangle "$OPTION" OUTPUT -m connmark --mark "$MARK" -j CONNMARK --restore-mark
}
ppp_origin() {
OPTION=$1
INTERFACE=$2
INIT_ID=$[400 + $(echo "$INTERFACE" | sed "s/ppp//g")]
INIT_ID_2=$[$INIT_ID + 110]
iptables -t mangle "$OPTION" PREROUTING -i "$INTERFACE" -m set ! --match-set mycard src -j CONNMARK --set-xmark "$INIT_ID"
restore_mark "$OPTION" "$INIT_ID"
}
ppp_origin -A ppp0
ppp_origin -A ppp1
,18002这里的 INIT_ID 与 PPPoE 的脚本吻合,对应两个 ppp 网卡。这里主要使用与 INIT_ID 相关的规则。INIT_ID_2 相关的规则将在下一节使用。
这样,每个宽带的入站请求都会打上 mark,通过 mark 把流量送回,而实现源进源出。
出站分流
说到这个,就是一个痛苦的话题了。各种出站的需求都不一样。很难有一个统一的出站分流方案。比如有些人想要最快的下载速度,用两份带宽同时下载。有些人需要银行这种场景的 IP 稳定性,不能让 IP 左右跳来影响 IP 触发网银风控。而有些情况下需要某些重要的人使用一份独立的宽带,其他人用其他宽带。
这里我们就分别说几种方案,分开来讨论。不过不管使用哪种方案,上面的源进源出的规则必须带着走,否则对外服务可能会出现问题。
Plan A: 均衡
均衡是最通用的一种方法。就是按均分所有的连接到每一个出口,进行带宽叠加。这种方法可以直接叠加带宽上去。但是呢对于网银等有些 IP 敏感的业务,可能会被风控。
下面上规则代码。注意需要与上面的 PPPoE 启动脚本一起使用,用于添加配合的 ip rule 策略路由。
ipset create mycard hash:net family inet || true
ipset add mycard 10.0.0.0/24 || true
ip rule add pref 80 to 10.0.0.0/24 lookup main || true
restore_mark() {
OPTION=$1
MARK=$2
iptables -t mangle "$OPTION" PREROUTING -m connmark --mark "$MARK" -j CONNMARK --restore-mark
iptables -t mangle "$OPTION" OUTPUT -m connmark --mark "$MARK" -j CONNMARK --restore-mark
}
ppp_origin() {
OPTION=$1
INTERFACE=$2
INIT_ID=$[400 + $(echo "$INTERFACE" | sed "s/ppp//g")]
INIT_ID_2=$[$INIT_ID + 110]
iptables -t mangle "$OPTION" PREROUTING -i "$INTERFACE" -m set ! --match-set mycard src -j CONNMARK --set-xmark "$INIT_ID"
restore_mark "$OPTION" "$INIT_ID"
}
ppp_origin -A ppp0
ppp_origin -A ppp1
iptables -t mangle -A PREROUTING -s 10.0.0.0/24 -m set ! --match-set mycard dst -m statistic --mode nth --every 2 --packet 0 -j CONNMARK --set-xmark 510
iptables -t mangle -A PREROUTING -s 10.0.0.0/24 -m set ! --match-set mycard dst -m statistic --mode nth --every 2 --packet 1 -j CONNMARK --set-xmark 511
restore_mark -A 510
restore_mark -A 511
注意这里的 iptables 规则顺序。源进源出规则必须在分流规则之前,避免内网对外服务失效。
Plan B: 奇偶 IP
Plan A 比较适合需要大量下载的场景。但是在需要访问外网源 IP 稳定的场景,这里奇偶 IP 的方法是比较好的,可以做到相同内网源 IP 和目标 IP 访问的出口 IP 一致。
首先,科普一下非标掩码的概念。在通常的情况下,子网掩码是从左往右叠加的。如 /24 的完整掩码是 255.255.255.0。在特殊的子网的情况下,不一定每一位是255。如 /22 是 255.255.252.0,是 /24 的 IP 数量的 4 倍。然而还有一种更特殊的,也就是我们这里需要用到的。形如 255.255.255.1这样的掩码,二进制分解之后就是 11111111.11111111.11111111.00000001,也就是判断前三端以及最后一段的最后一位,表示的意思是 “头三段完全一致以及最后1位一致” 的地址。
这里的用途在于,可以构造一个非标掩码子网段,用来把一个网段分割成两部分,按奇偶分开,实现负载均衡。如 10.0.0.0/255.255.255.1 为内网内 IP 末位是偶数的地址,而 10.0.0.1/255.255.255.1 则为内网内 IP 末位是奇数的地址。类似的,0.0.0.0/0.0.0.1则为全部 IP 末位是偶数的地址,0.0.0.1/0.0.0.1 同理。
非标掩码支持的地方有限。目前只知道 iptables 支持,但是 ip rule 不支持。因此规则如下。
ipset create mycard hash:net family inet || true
ipset add mycard 10.0.0.0/24 || true
ip rule add pref 80 to 10.0.0.0/24 lookup main || true
restore_mark() {
OPTION=$1
MARK=$2
iptables -t mangle "$OPTION" PREROUTING -m connmark --mark "$MARK" -j CONNMARK --restore-mark
iptables -t mangle "$OPTION" OUTPUT -m connmark --mark "$MARK" -j CONNMARK --restore-mark
}
ppp_origin() {
OPTION=$1
INTERFACE=$2
INIT_ID=$[400 + $(echo "$INTERFACE" | sed "s/ppp//g")]
INIT_ID_2=$[$INIT_ID + 110]
iptables -t mangle "$OPTION" PREROUTING -i "$INTERFACE" -m set ! --match-set mycard src -j CONNMARK --set-xmark "$INIT_ID"
restore_mark "$OPTION" "$INIT_ID"
}
ppp_origin -A ppp0
ppp_origin -A ppp1
iptables -t mangle -A PREROUTING -m mark --mark 0 -s 10.0.0.0/255.255.255.1 -d 0.0.0.0/0.0.0.1 -m set ! --match-set mycard dst -j CONNMARK --set-xmark 510
iptables -t mangle -A PREROUTING -m mark --mark 0 -s 10.0.0.1/255.255.255.1 -d 0.0.0.0/0.0.0.1 -m set ! --match-set mycard dst -j CONNMARK --set-xmark 511
iptables -t mangle -A PREROUTING -m mark --mark 0 -s 10.0.0.0/255.255.255.1 -d 0.0.0.1/0.0.0.1 -m set ! --match-set mycard dst -j CONNMARK --set-xmark 511
iptables -t mangle -A PREROUTING -m mark --mark 0 -s 10.0.0.1/255.255.255.1 -d 0.0.0.1/0.0.0.1 -m set ! --match-set mycard dst -j CONNMARK --set-xmark 510
restore_mark -A 510
restore_mark -A 511
这里奇偶性错位稍微有一点小技巧。这里把源和目标 IP 奇偶性相同的放在一个宽带里面,把不同的放在另一个宽带里面。至于为什么这么错位,是为了保证,在不同内网机器访问同一外网网站,以及同一内网机器访问不同外网网站的情况下,都能把流量分开。
题外话
本文的场景都是 PPPoE 或者其他三层隧道的情况下的分流。如果是 IDC 网络,涉及三层寻址找网关的,则需要这么写源进源出规则。
ppp_origin() {
OPTION=$1
ADDRESS=$2
NEIGH_LINE=$(ip neigh show $ADDRESS)
INTERFACE=$(echo $NEIGH_LINE | awk '{print $3}')
MAC=$(echo $NEIGH_LINE | awk '{print $5}')
INIT_ID=$3
INIT_ID_2=$[$INIT_ID + 110]
iptables -t mangle "$OPTION" PREROUTING -i "$INTERFACE" -m mac --mac-source $MAC -m set ! --match-set mycard src -j CONNMARK --set-xmark "$INIT_ID"
restore_mark "$OPTION" "$INIT_ID"
}
这里第二个参数是机房提供的网关的 IP 地址,第三个参数是 mark 以及 table 的取值。
关于 Minecraft
2019-09-03Minecraft 是一个沙盒类游戏,自由度很高,玩家可以创作自己喜欢的东西,也可以运营一个自己的服务器给大家参观或者玩耍。
这也给 Minecraft 服务器出租带来了不少市场。于是市面上出现了不少的 Minecraft 服务商,提供 Minecraft 服务器出租业务,赚了不少。恋恋也有点想入这个局,利用现有的服务器资源,提供 Minecraft 服务器出租,来补贴一些服务器的租金支出。
恋恋之前卖过少量的 VPS 服务器供客户搭建 Minecraft 服务器使用。但是总有人觉得 VPS 使用难度比较大,隔一段时间就有人问我 Minecraft 服务器怎么安装,或者 Java 怎么安装,甚至是让恋恋帮他们调试他们的服务端。恋恋自己对Minecraft 服务器的了解程度有限,只能从运维的角度来帮忙解决问题。而遇到具体到应用的问题,恋恋也只能查阅文档来进行处理。令人沮丧的是,还有人觉得 VPS 不好用,偏要用面板服。
借助一次契机,恋恋和 MyCard 的人员搭建好了一个翼龙面板,让出租简单易用 Minecraft 面板服成为了可能。由于翼龙基于 Docker 环境,服务器被熊被提权的概率小了好多。此外,也研究好了 WHMCS 的系统,让销售服务器变成了自动化过程,省了好多事,可以自动化出售服务器。
但是,恋恋通过一些渠道了解到,Minecraft 的圈子有一些不太好的地方。如,有些玩家脾气非常怪异,和服务器其他人相处有问题就对服务器发动 DDoS 攻击,让服务器的主人以及服务商陷入难堪。而且,服务器遭到 DDoS 攻击还会影响其他的生产环境的应用,带来一定的损失。因此,恋恋只能在路由策略上下一点工夫,让遭到 DDoS 带来的损失降到最小。
恋恋目前在犹豫的是,自己和 MyCard 这边,相比其他商家能带来什么优势呢?其他服务商的服务器动不动就是好几线 BGP 线路,优势非常大。恋恋这边只能使用部署过的冗余的机器进行搭建,效果没那么好。Minecraft 服务器出租,到底又什么出路呢?
Libevent 2.1
2019-07-09自从YGOPro的1.034.B版本开始,终于可以用上libevent 2.1了。
之前恋恋苦苦每次安装服务器的时候,都得编译安装libevent 2.0.22才能装好。直接使用apt安装libevent最新版本的话,非常容易决斗结束的时候挂掉,非常气。Docker也是,有一大段RUN语句,用来编译安装的。改了之后,所有的环境安装,一个RUN apt install …..就够了。
不过YGOPro的修改过程可谓非常艰辛。YGOPro客户端夏娜这么改之后,libvent就可以用最新版本了。然而,在YGOPro服务端就是另一个景象了。恋恋找了好久原因服务器为什么会卡住。结果各种方法都尝试了。最后发现,其实就是一个非常细小的问题。
不管怎么说,能用libevent 2.1是一个非常大的进步,再也不需要编译安装libevent 2.0.22了。不少兼容性问题也得到了解决。
最近超级累
2019-07-09恋恋终于放假了,总算不需要每周末跑回学校浪费时间了。
但是,另一方面,又开始累了。各种YGOPro开发运维的东西,一天恋恋就什么都不想做,就想躺在床上睡觉。(恋恋就是被被子封印了)
谁能解开恋恋的被子的封印呢?
东方联机暴露IP的弊端
2019-06-22在国内,大家要联机《东方非想天则》的时候,一般会选用MyCard这样的平台,为第三方提供内网穿透的平台,来解决NAT或者CGN等得不到公网IP的问题。
但是,在国外,在公网IP资源比较富裕的地方,经常就是直接把IP暴露在房间列表里面,挂出来让大家联机使用。例如在则的Discord群里面,有一个Discord Bot的房间列表,大概是这样的。
ParvatiBOT05/25/2018 Current Hosts are:(UTC-04:00)
For 8m 55.0s R 1.3Yosupall
170.52.96.89:10800
(edited) NEW MESSAGES ParvatiBOTToday at 9:36 AM Last Changes: @soku(UTC-04:00)
For 2.8s R 1.3Yosupall
170.52.96.89:10800
这种平台,自己的IP直接暴露给大家看,用来连接对方的电脑直接打。但是呢,不太好的地方是,如果是电脑直接连接公网,或者路由器设置了DMZ的话,如果电脑没有做适当的安全配置,电脑很容易被黑掉。尤其是135,139,445,3389这几个端口是重灾区。
在一些国内的则群里面,还甚至有人把自己的电脑IP挂在自己的群名片上面,方便大家联机。这也是安全隐患的来源之一。不过大部分人都是用路由器NAT上网,只开一个10800端口应该问题不是很大。虽然只开10800/udp也会被UDP Flood让家里断网。
在这里,恋恋推荐大家使用Wireguard搭建反向代理隧道,用iptables或者Nginx转发则的流量玩则。或者,不会的话。使用MyCard来联机则也是一个很好的选择。这样自己使用的IP就是一次性的,不会带来额外的安全风险。
DDNS的那些事
2019-06-08DDNS是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器程序负责提供DNS服务并实现动态域名解析。
DDNS有一个最大的用途就是,可以在一般的动态公网IP的宽带上搭建服务器。最开始恋恋听说这个技术的时候,其实还是挺反感的,觉得用这个方法开服务器的人都是穷人,没钱买IDC的服务,或者阿里云的这些。
后来呢,恋恋和zh99998约会的那一次,恋恋改变了这个印象。因为DDNS开的服务器,除了一点点TTL的问题以外,都开得很好。于是呢恋恋也尝试了一下,用no-ip的服务开Yuzurisa服务器。结果表现得比恋恋想象的好很多。Yuzurisa服务器正式上线之后,因为家庭带宽非常的大,有50M上500M下,足够对外提供服务,所以表现得比想象中好很多。
再后来,恋恋就想充分利用各种家里能用的带宽来开服务器。恋恋入手了Ayane服务器,利用另一个房子的带宽,成功让服务器上线。Ayane服务器运行的还不错。目前位置,恋恋在Ayane服务器上部署了好几个KVM虚拟机。
一般的宽带都是封80端口的,防止私人建站。目前的解决方法是,用没有封闭的443端口通过HTTPS建站。另外,还可以加一层HSTS来防止用户敲错成HTTP。不过恋恋听说过Sakura Frp的那批人的家庭宽带被封的情况,但愿不要遇到吧。
但是DDNS很尴尬的地方就是,IP变的交接时间,服务器就访问不到了,业务也中断了。虽说名义上人家的DNS的TTL写的是10分钟,可是实际上部分黑心运营商的DNS服务器会人为放大TTL,就导致DNS的延迟更长。如果这发生在比赛的时候,就非常麻烦。
所以说,DDNS的确是一个成本很低的解决方案,不需要缴纳昂贵的IDC托管费用,就能用比较大的带宽完成业务部署。不过另一方面,TTL的问题还是挺让人头疼的。总的来说,有得有失吧。
有点想写新谱了
2019-06-07恋恋好久没些新的太鼓次郎谱了,主要还是Ubuntu上面没有工具可以调offset,也没有办法剪辑音乐。本来Malody上面是有自动调offset的工具的,可惜Malody没办法在恋恋的电脑上运行,就好尴尬。
最近恋恋听了不少叶月的歌,都是那种魔女风格的。恋恋特别想写个HAMELN的谱。但是歌曲好长,有3分42秒,很难剪短。恋恋也没掌握那种无缝剪辑的高科技。要是能写好的话,恋恋就挂到Taiko Web上面去。
有没有人帮忙实现恋恋的心愿呢?
重复听歌的弊端
2019-06-03有时候恋恋特别喜欢单曲循环听歌,比如之前的《宵暗花火》,恋恋就每天都单曲循环听。听到最后就没感觉了。每次随机到《宵暗花火》,恋恋就想点下一首。
还有一次,恋恋半夜睡觉开着《恋咏樱》单曲循环,结果第二天早上醒来满脑子都是《恋咏樱》,歌曲本身音调也变了,好几天才缓过来,重新找到感觉。这到底是为什么呢?
网易云音乐的随心模式就特别好,能帮助找到许多新歌,也不会因为单曲循环听腻。