分类 RouterOS 下的文章

RouterOS单系统实现透明网关

20231218更新:优化hysteria启动脚本。

自从接触mikrotik公司的RouterOS系统以来,一直都想以routeros单系统实现内外网自动分流、dns防污染的透明网关。
由于routeros是商业公司开发的闭源路由系统,虽然是基于linux内核,但是并不像openwrt一样可以安装任意软件。
所以在v6版本时代尝试过ipsec、ipip、gre隧道等方式穿墙,效果并不是很好,要么会受到墙的干扰,要么运营商qos太厉害,
要么协议本身限制再公网跑不起速度来。

所以引入了openwrt旁路由,routeros导入国内IP地址表,通过rooting mark的方式实现国内外IP地址分流,把国外IP地址转发给openwrt,openwrt通过ssr+或者passwall等使用ss、ssr、trojen、vless、hysteria等穿墙协议实现国外流量送出墙。

由于openwrt自身的复杂、开源软件质量,以及编译时的细节选项的各种问题,导致openwrt并不是十分稳定,且排查较为困难。
一直认为使用openwrt作为旁路由并不完美。后来routeros系统增加了wireguard,选择合适线路的vps后,可以实现勉强能做到单系统的透明网关,但是最近一段时间wireguard被墙阻断越来越严重,更换端口勉强能用几天。
再后来routeros内置了容器功能,极大的增大了发挥空间,虽然是个严重严格的容器功能。

通过以容器方式起mosdns实现了dns防污染、IPv4和IPv6自定义优先级等功能。
最近研究了一些前人的教程方法后,实现了容器内clash、sing-box、hysteria等程序路由功能。

RouterOS容器实现路由方式穿墙的方法,以hysteria这个简单程序为例。
1,通过hub.docker.com远程仓库拉去镜像或者导入tar文件方式创建容器。
以tar文件方式为例
电脑安装docker desktop并启动
命令行

docker pull alpine
docker save -o alpine.tar alipine

如果routeros是arm版的话

docker pull alpine@sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281
#sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281可在docker hub的网页上找到

2,然后把tar文件上传到routeros,建议开启smb功能,通过smb新建的文件权限比sftp或者scp要高
3,然后是创建容器,详细参考官方文档
创建完后,修改cmd属性

tail -f /dev/null

然后启动容器
4,通过shell 0 容器编号进入容器字符界面
使用wget命令下载hysteria,并解压
创建hysteria的配置文件,供参考,以服务端配置为准

{
  "insecure": true,
  "protocol": "wechat-video",
  "down_mbps": 330,
  "server": "x.x.x.x:x",
  "tun": {
  "name": "tun0"
  },
  "auth_str": "xxxx",
  "disable_mtu_discovery": false,
  "up_mbps": 110,
  "alpn": "h3",
  "server_name": "wechat.com"
}

5,然后创建tun

apk update
apk add iproute2
ip tuntap add mode tun dev tun0
ip addr add 198.18.0.1/15 dev tun0
ip link set dev tun0 up

6,修改路由,可以通过修改默认路由metric方式
假设 eth0 是原本的网卡,网关地址为 192.168.1.1,x.x.x.x是vps的IP地址

ip route del default
ip route add default via 198.18.0.1 dev tun0 metric 1
ip route add default via 192.168.1.1 dev eth0 metric 10
ip route add 192.168.0.0/16 via 192.168.1.1
ip route add 10.0.0.0/8 via 192.168.1.1
ip route add x.x.x.x via 192.168.1.1

也可以通分解0.0.0.0/0方式添加路由

ip route add 0.0.0.0/1 via 198.18.0.1
ip route add 128.0.0.0/1 via 198.18.0.1
ip route add 192.168.0.0/16 via 192.168.1.1
ip route add 10.0.0.0/8 via 192.168.1.1
ip route add x.x.x.x via 192.168.1.1

7,退出容器,停止容器
修改容器cmd参数

/root/hysteria client --config /root/hk.json

启动容器
8,配置routeros转发国外流量给容器,参考Routeros V7配置策略路由

9,容器内hysteia一键启动脚本start.sh

#!/bin/sh
GW="192.168.1.1"
cp /hysteria/hysteria /bin/
ip route replace 10.0.0.0/8 via $GW
ip route replace 192.168.0.0/16 via $GW
awk -F'"|:' '/"server"/ {cmd="ip route replace "$5" via '$GW'";system(cmd)}' /hysteria/$1
sleep 2&&ip addr add 198.18.0.1 dev tun0&&ip link set dev tun0 up&&ip route replace default via 198.18.0.1 &
hysteria client --config /hysteria/$1

在routeros上传hysteria可执行文件、hysteria配置文件和上面启动脚本到/container/etc/hysteria里
routeros新建容器命令

/container/mounts add name="hysteria" src="/container/etc/hysteria" dst="/hysteria"
/container add file=container/tmp/alpine_v3.18.2.tar interface=container-hysteria hostname=hysteria mounts=hysteria root-dir=container/root-dir/hysteria cmd="sh /hysteria/start.sh hk.json" start-on-boot=yes
/container start [find hostname=hysteria]

说明
由于routeros的容器功能细节一直在变动,有时候上一个版本还能使用,更新之后容器就不能启动了,而且日志一点信息都没有,所以采取了最保守的方式手动配置容器内应用的方式。
容器的网卡配置既不在容器内部存储,也不在routeros的veth里存储,似乎在一个容器外部不可见的地方,只能在容器内部操作,删除重建容器使用原来veth发现原有tun、静态路由居然还在。在routeros里修改veth的ip地址,居然不会同步修改容器内IP地址。
7.6版能启动的openwrt容器,新版就不能启动,一点日志都没有。
之前容器内可以写入mount的目录,新版就没有写权限,也没有执行权限,虽然容器内显示有权限。

也研究了tinyserve的bird+clash容器实现ospf动态路由透明网关方式,他使用了s6在容器内看护了几个应用,导致容器内存需求较大,小于4G内存的就别测试了。我使用rb5009,内存只有1gb,遇到routeros内存不足重启的问题。
动态路由这种透明网关方式早在ssr出现之前就有人提出,使用树莓派上跑bird+ss实现,但是我一直觉得一旦穿墙失效,所有数据包都会被运营商和墙捕捉到,为了高可用牺牲安全性不太值得,所以一直没用。

RouterOS在ESXi8.0上以UEFI方式引导启动

最近新装了虚拟化平台esxi8.0b,在创建routeros虚拟机时遇到了一系列问题:
1,esxi8.0b默认创建的ESXi 8.0(虚拟硬件版本20)版本虚拟机使用了新的api,默认以uefi引导系统,在创建完成后不能修改为bios,报错“ACPI motherboard layout requires EFI”。
2,RouterOS的CHR版磁盘镜像默认以bios引导。使用x86的iso可以正常安装使用uefi引导虚拟机,但是系统显示的是x86架构,通过升降级不能切换架构,x86架构不启用open-vm-tools服务,这个服务不启动,在esxi控制面板看不到hostname和IP地址等信息。此外x86架构和chr架构的授权和有些功能也不相同。
3,RouterOS的CHR版磁盘镜像有两个分区,第一个是efi分区,文件系统是ext2,而非uefi标准的fat。
4,RouterOS的CHR版磁盘镜像有独立的mbr和gpt分区表,既不是gpt也不是Hybrid MBR。
5,RouterOS的CHR版uefi启动不支持Secureboot。

以下是让routeros v7.8在ESXi8.0上以UEFI方式引导启动的方法,此方式只在routeros v7.8chr版测试通过,不确定后续版本升级是否可用。
1,创建没有硬盘的虚拟机,关闭secureboot。
2,下载routeros的vmdk虚拟机硬盘文件,解压上传到esxi。
3,ssh登录到esxi,转换routeros的vmdk磁盘格式,并扩展磁盘空间。

vmkfstools -i chr-7.8.vmdk routeros.vmdk -d thin
vmkfstools -X 20G routeros.vmdk

4,修改虚拟机配置,添加刚才生成的vmdk磁盘。
5,虚拟机挂载ubuntu的live-cd或其他有gdisk命令的系统iso到虚拟机。
6,开机进入ubuntu桌面,备份RouterOS Boot分区的全部文件
7,取消挂载,并使用fat格式化第一个分区

mkfs -t fat /dev/sda1

8,恢复步骤6中备份的文件到第一个分区后取消挂载routeros的两个磁盘
9,使用gdisk创建Hybrid MBR分区表,过程如下:

root@ubuntu:/home/ubuntu# gdisk /dev/sda
GPT fdisk (gdisk) version 1.0.8

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: present

Found valid MBR and GPT. Which do you want to use?
 1 - MBR
 2 - GPT
 3 - Create blank GPT

Your answer: 2
Using GPT and creating fresh protective MBR.

Command (? for help): t
Partition number (1-2): 1
Current type is EF00 (EFI system partition)
Hex code or GUID (L to show codes, Enter = EF00): 8300
Changed type of partition to 'Linux filesystem'

Command (? for help): r

Recovery/transformation command (? for help): h

WARNING! Hybrid MBRs are flaky and dangerous! If you decide not to use one,
just hit the Enter key at the below prompt and your MBR partition table will
be untouched.

Type from one to three GPT partition numbers, separated by spaces, to be
added to the hybrid MBR, in sequence: 1 2
Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? (Y/N): n

Creating entry for GPT partition #1 (MBR partition #1)
Enter an MBR hex code (default 83): 
Set the bootable flag? (Y/N): y

Creating entry for GPT partition #2 (MBR partition #2)
Enter an MBR hex code (default 83): 
Set the bootable flag? (Y/N): n

Unused partition space(s) found. Use one to protect more partitions? (Y/N): n

Recovery/transformation command (? for help): w
Warning! Secondary header is placed too early on the disk! Do you want to
correct this problem? (Y/N): y
Have moved second header and partition table to correct location.

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.

10,重启系统即可以UEFI方式启动RouterOS CHR

附:
初始vmdk的mbr分区表:

root@ubuntu:/home/ubuntu# gdisk /dev/sda
GPT fdisk (gdisk) version 1.0.8

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: present

Found valid MBR and GPT. Which do you want to use?
 1 - MBR
 2 - GPT
 3 - Create blank GPT

Your answer: 1

Command (? for help): p
Disk /dev/sda: 262144 sectors, 128.0 MiB
Model: VMware Virtual I
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): F1C07EE3-729F-4E5F-8C77-AEC9BC697BD3
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 262110
Partitions will be aligned on 2-sector boundaries
Total free space is 4063 sectors (2.0 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              34           65569   32.0 MiB    8300  Linux filesystem
   2           65570          258047   94.0 MiB    8300  Linux filesystem

Command (? for help): q

初始vmdk的gpt分区表:

root@ubuntu:/home/ubuntu# gdisk /dev/sda
GPT fdisk (gdisk) version 1.0.8

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: present

Found valid MBR and GPT. Which do you want to use?
 1 - MBR
 2 - GPT
 3 - Create blank GPT

Your answer: 2
Using GPT and creating fresh protective MBR.

Command (? for help): r

Recovery/transformation command (? for help): p
Disk /dev/sda: 262144 sectors, 128.0 MiB
Model: VMware Virtual I
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 197E76F1-9677-0D46-9C33-F00032DDDBB1
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 258047
Partitions will be aligned on 2-sector boundaries
Total free space is 0 sectors (0 bytes)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              34           65569   32.0 MiB    EF00  RouterOS Boot
   2           65570          258047   94.0 MiB    8300  RouterOS

Recovery/transformation command (? for help): q

创建hybrid mbr后的vmdk的gpt分区表:

Recovery/transformation command (? for help): p
Disk /dev/sda: 262144 sectors, 128.0 MiB
Model: VMware Virtual I
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 197E76F1-9677-0D46-9C33-F00032DDDBB1
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 258047
Partitions will be aligned on 2-sector boundaries
Total free space is 0 sectors (0 bytes)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              34           65569   32.0 MiB    8300  RouterOS Boot
   2           65570          258047   94.0 MiB    8300  RouterOS

Recovery/transformation command (? for help): o

Disk size is 262144 sectors (128.0 MiB)
MBR disk identifier: 0x00000000
MBR partitions:

Number  Boot  Start Sector   End Sector   Status      Code
   1      *             34        65569   primary     0x83
   2                 65570       258047   primary     0x83
   3                     1           33   primary     0xEE

参考:
1,Router OS 7 on UEFI
2,Hybrid MBR(MBR 混合分区表)
3,Manual:CHR VMWare installation

RouterOS使用DNS转发功能实现域名分流解析

20220718更新:更新域名匹配正则,添加每周更新脚本。由于缓存查询时间增加过多,此方法不推荐,详情参考文章后部。

之前写过两篇文章介绍实现域名分流解析的方案,一个是使用dnsmasq基于大陆域名白名单分流解析域名,另一个是使用overture替换dnsmasq做域名分流解析
这次介绍的方案与dnsmasq类似,默认使用境外dns服务器解析,境内域名使用白名单转发到境内dns服务器。
routeros在v6.47中增加了静态条目规则type属性,其中包含FWD类型。FWD类型可以将指定域名转发到指定的DNS服务器。
以下以routeros v7.3.1的chr版本为环境,dns服务器是8.8.8.8和8.8.4.4
增加alicdn.com域名及子域名转发给114.114.114.114解析。正则匹配如下

^(.*\.)?alicdn\.com$

命令如下

/ip/dns/static/add regexp="^(.*\\.)?alicdn\\.com\$" forward-to=114.114.114.114 ttl=300s

详细命令请参考官方wiki
这里使用dnsmasq-china-list做白名单转发给境内dns服务器解析,生成脚本如下

/ip/dns/static/remove [/ip/dns/static/find type=FWD]
/ip/dns/static/add regexp="^(.*\\.)?0-100\\.com\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?0-6\\.com\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?00\\.net\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?000\\.link\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?00000\\.host\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?00042\\.com\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?00058\\.com\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?0006266\\.com\$" forward-to=114.114.114.114 ttl=300s
/ip/dns/static/add regexp="^(.*\\.)?0007\\.net\$" forward-to=114.114.114.114 ttl=300s
...

脚本有接近7万行,使用intel i5-7200u分配2逻辑核心的虚拟机首次执行需要约3.5分钟,阿里云1核心服务器首次执行需要2.5分钟,再次执行需要7.5分钟,再次执行时会先删除type=FWD的静态条目,脚本执行时cpu占用100%,所以cpu性能较差时需要耐心等待。

这里下载每周自动生成的脚本。
导入方法:使用

/import dns.rsc

导入,等待完成。

使用RouterOS自带dns转发功能做域名分流解析优点是可以抛弃openwrt或者linux服务器的小尾巴,实现routeros单一系统完成全部网络功能,特别适合不支持直通的cpu裸装routeros的情况。
缺点和使用dnsmasq分流解析一样,境内域名列表更新不及时,可能导致一些新的域名解析成境外地址。

另外,导入dns转发脚本后不要使用webfig打开dns静态列表,条目太多会卡死。
附:自动生成dns.rsc脚本

#!/bin/bash
echo "/ip/dns/static/remove [/ip/dns/static/find type=FWD]">/tmp/dns.rsc && curl -s https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/accelerated-domains.china.conf|sed '/#/d'|sed 's/\/114.114.114.114//g'|sed 's/\./\\\\./g'|sed 's/server=\//\/ip\/dns\/static\/add regexp=\"^(.*\\\\.)?/g'|sed 's/$/&\\$\" forward-to=114.114.114.114 ttl=300s/g'>>/tmp/dns.rsc

发现问题:
1,routeros的dns本地缓存查询时间显著增加,使用dig命令发现未导入时缓存查询时间小于1ms,导入后缓存查询时间约28ms,白名单域名反而查询时间更短。
2,在dns设置增加缓存到1gb后观察,发现导入后占用约180mb缓存。另可以通过观察缓存大小来大致确定导入进度。

windows单网卡实现802.1x认证的有线网络共享

以下内容仅适合我的特殊网络情况,仅供参考。

公司使用的是标准802.1x有线互联网认证,认证策略是PEAP/EAP-MSCHAPv2(不验证认证服务器证书)。这种认证策略在桌面操作系统支持的比较好,windows、mac、ubuntu都没有问题,但是在品牌路由器上能很好支持的基本没有。以linux为基础的vyos可以使用linux软件间接实现,openwrt同理,routeros声称可以支持,但是认证策略是PEAP时需要CA证书验证服务器身份切不能关闭,所以routeros也不行。

想使用网络共享是为了给手机wifi,笔记本本来是有移动热点功能的,结果intel的ax200无线网卡与iphone等设备有兼容性问题(表现为wifi连接成功, 不能获取IP地址),且只能使用2.4g频段(可以通过连接5gwifi后再共享的方式破解限制)。

中间使用过usb网卡共享网络给路由器,结果usb网卡在windows下稳定性太差,经常使用一段时间后就消失,只能重启恢复。

最终方案是,笔记本电脑网卡开启vlan功能,一根网线两个vlan,一个vlan走802.1x认证,另一个vlan共享网络。

设备:机械革命CODE01笔记本(realtek有线网卡),路由器mikrotik hap ac2(routeros v7.1beta6)

下载并安装Realtek Ethernet Diagnostic Utility,启用网卡vlan功能,创建vlan10和vlan20分别用于802.1x认证和网络共享。启用vlan后会虚拟出两个网卡,分别对应vlan10 和vlan20,在Utility中修改vlan10虚拟网卡的mac地址为物理网卡mac地址(802.1x绑定了mac地址、用户名和密码)。

routeros使用交换芯片的硬vlan,软vlan经过测试有问题(也可能配置有问题)

/interface/ethernet/switch/vlan
/interface/ethernet/switch/port
/interface/bridge/vlan
/interface/vlan
/ip/address/

routeros配置待完善。

Routeros V7配置策略路由

20230529更新:增加ipv6策略路由实现境内外ipv6地址分流的方法。

在两年前我写过一篇routeros配置vpn分流大陆ip的文章,里面主要介绍了使用routeros基于源地址和目的地址的策略路由。在使用Routeros V7 测试版的过程中发现V7相比于V6版在路由配置方便有很大变更,所以这篇文章会以Routeros V7为基础介绍策略路由的配置。

网络基本情况
routeros作为家庭唯一路由,通过pppoe接入互联网,通过wireguard连接香港的routeros。

策略路由目标
1,需要翻墙的内网ip:目的地址是境内ip走pppoe默认路由,目的地址是境外IP走wireguard通过香港routeros进入墙外互联网
2,其他内网ip全部走pppoe默认路由

IP地址分配参考上一篇文章Routeros 配置WireGuard

本地lan的地址是192.168.1.1/24,wg-access地址是10.0.0.1/24,wg-hk的地址是10.0.1.1/30,手机wireguard的地址是10.0.0.2/32,笔记本电脑的地址是10.0.0.3/32
香港wg0地址是10.0.1.2/30

配置步骤
1,导入大陆IP地址表
参考Routeros的address-list大陆分流列表
把cnip.rsc上传到routeros,执行

/import cnip.rsc

2,配置分流路由表
Routeros V7取消了通过firewall的mangle里添加路由标记自动添加路由表功能,所有这里需要手动添加路由表

/routing/table/add name="gfw" fib

添加IP分流策略路由

/ip/route/add dst-address=0.0.0.0/0 routing-table="gfw" gateway=10.0.1.2

3,新建需要翻墙的内网地址列表,假定192.168.1.100和192.168.1.200需要翻墙

/ip/firewall/address-list/add list=gfw address=192.168.1.100/32
/ip/firewall/address-list/add list=gfw address=192.168.1.200/32

4,给需要翻墙的内网ip添加标记

/ip/firewall/mangle/add chain=prerouting action=mark-routing new-routing-mark=gfw passthrough=yes dst-address-type=!local src-address-list=gfw dst-address-list=!CNIP log=no log-prefix=""

5,配置无污染DNS服务器
参考使用dnsmasq基于大陆域名白名单分流解析域名使用overture替换dnsmasq做域名分流解析

6,测试目的IP分流
在192.168.1.100上执行traceroute命令

traceroute 8.8.4.4
192.168.1.100--->192.168.1.1--->10.0.1.2--->香港服务器公网路由--->8.8.4.4
traceroute 114.114.114.114
192.168.1.100--->192.168.1.1--->PPPoE公网路由---->114.114.114.114

ps,按照上述ipv4的策略路由配置方法,ipv6并不会生效。
此问题是ipv6策略路由的路由表问题。截至v7.10beta8,mikrotik还没有修复ipv6的路由表问题,或者是mikrotik将来会调整策略路由配置方法。
ipv6的firewall的对应mangle条目的counter有计数,说明修改routing-mark已经生效,但是数据包没有走routing-mark设置的路由表。
经过搜索mikrotik官方论坛,需要另外增加一条设置

/routing/rule/add action=lookup-only-in-table routing-mark=gfw table=gfw