MikroTik RB4011 访客网络配置备忘

前言

Speedtest
由于之前陆陆续续添置了不少电子设备,以及更换 ISP 的原因,机架上连了5台设备,每台各负责一点点事情,不管是配置还是调试都很麻烦。再加上旧路由器不能很好同时处理千兆 NAT 和 VLAN,于是最近入手了一台 RB4011iGS+5HacQ2HnD-IN,把这一堆乱七八糟的设备统统换掉。主要需求有三点:

  1. 划分2个 VLAN,一个内部网络,一个访客网络。
  2. IPv4 和 IPv6 双栈接入。
  3. 因为路由器直接暴露在 Internet 上了,所以防火墙一定要配好,包括 VLAN 之间的访问也是靠防火墙来控制的。

WinRAR 恢复记录添加及使用教程

本文中的所有图片及文字均使用 CC0 发布,可任意转载使用。

本文属于疫情期间的摸鱼之作,旨在推广 RAR 压缩格式的正确压缩方法,让资源分享更轻松一些。

获取 WinRAR

先说一下为什么用 WinRAR 而不用 7zip, 因为 7zip 没有恢复记录。在百度网盘等平台分享文件时,文件可能发生损坏,没有恢复记录的话只能尝试重新下载浪费时间,而有恢复记录的话有大概率可以成功修复,正确解压。

国内特供版的 WinRAR 可以免费使用,但是有广告。如果不想要广告,你可以从以下链接下载官方无广告简体中文版

https://www.win-rar.com/fileadmin/winrar-versions/sc/sc20200409/rrlb/winrar-x64-590sc.exe

注意,如果你没有rarreg.key文件进行注册的话依然是有广告的。至于具体的注册方法请自行搜寻。

CMake 项目生成脚本

C++ 比较尴尬的一点就是缺少比较“傻瓜”的工具库,不得不依靠第三方来补充。想快速开始写个小的 Demo 的时候光找库就花去不少时间。于是糊了一个脚本去自动生成这些基础的东西。放在这里方便自己以后参考。

用到的库列表:

  • {fmt}: 字符串格式化库
  • spdlog: 日志
  • backward-cpp: 崩溃时的堆栈输出
  • benchmark: 快速性能测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/bin/bash

print_help() {
echo "Usage:"
echo " cproject <type> <name>"
echo "Types:"
echo " bin, bench"
}

die() {
echo "Unexpected error"
exit 2
}

# Ninja does not work with backward-cpp
new_bin() {
local name="$1"
mkdir "$name" || die
cd "$name" || die
git clone 'https://github.com/fmtlib/fmt.git' third_party/fmt || die
git clone 'https://github.com/bombela/backward-cpp.git' third_party/backward-cpp || die
git clone 'https://github.com/gabime/spdlog.git' third_party/spdlog || die
cat << EOF > CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(${name})

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_FLAGS "\${CMAKE_CXX_FLAGS} -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "\${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0")
set(CMAKE_EXE_LINKER_FLAGS "\${CMAKE_EXE_LINKER_FLAGS} -rdynamic")

add_subdirectory(third_party/fmt)
add_subdirectory(third_party/spdlog)
add_subdirectory(third_party/backward-cpp)

add_executable(main)
target_sources(main PRIVATE main.cpp \${BACKWARD_ENABLE})
target_link_libraries(main PRIVATE fmt spdlog -ldw)
EOF

cat << 'EOF' > main.cpp
#include <iostream>
#include <string>
#include "fmt/format.h"
#include "spdlog/spdlog.h"

#define CRASH(...) \
{ ::spdlog::critical(__VA_ARGS__); \
int _ [[maybe_unused]] = \
*reinterpret_cast<int*>(0); }

inline int get_return_code() {
CRASH("unimplemented function: {}", __func__);
return 0;
}

int main(int argc, char* argv[]) {
fmt::print("{}, {}\n\n", "hello", "world");

spdlog::set_level(spdlog::level::debug);
spdlog::debug("debug message");
spdlog::info("info message");
spdlog::warn("warning message");
spdlog::error("Some error message with arg: {}", 1);
return get_return_code();
}
EOF
echo
echo "Skeleton generated. Run the command and you shall see " \
"the stacktrace demo."
echo " cd ${name} && cmake -B build && " \
"make -C build -j main && build/main"
}

new_bench() {
local name="$1"
mkdir "$name" || die
cd "$name" || die
git clone 'https://github.com/fmtlib/fmt.git' third_party/fmt || die
git clone 'https://github.com/bombela/backward-cpp.git' third_party/backward-cpp || die
git clone 'https://github.com/gabime/spdlog.git' third_party/spdlog || die
git clone 'https://github.com/google/benchmark.git' third_party/benchmark || die
git clone 'https://github.com/google/googletest.git' third_party/benchmark/googletest || die
cat << EOF > CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(${name})

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_FLAGS "\${CMAKE_CXX_FLAGS} -Wall -Wextra -g")
set(CMAKE_EXE_LINKER_FLAGS "\${CMAKE_EXE_LINKER_FLAGS} -rdynamic")

set(BENCHMARK_ENABLE_LTO true)

add_subdirectory(third_party/fmt)
add_subdirectory(third_party/spdlog)
add_subdirectory(third_party/backward-cpp)
add_subdirectory(third_party/benchmark)

add_executable(bench)
target_sources(bench PRIVATE bench.cpp \${BACKWARD_ENABLE})
target_link_libraries(bench PRIVATE fmt spdlog benchmark::benchmark_main -ldw)
EOF

cat << 'EOF' > bench.cpp
#include "benchmark/benchmark.h"
#include <cinttypes>
#include <cstdlib>

constexpr size_t ARRAY_LEN = 1024*64;
static void BM_SeqArrayAccess(benchmark::State& state) {
int stride = state.range(0);
uint64_t arr[ARRAY_LEN];
for (auto _ : state) {
for (size_t idx = 0; idx < ARRAY_LEN; idx += stride) {
arr[idx] = random();
}
}
}
BENCHMARK(BM_SeqArrayAccess)
->Arg(1)
->Arg(2)
->Arg(3)
->Arg(4)
->Arg(5)
->Arg(6)
->Arg(7)
->Arg(8);
EOF
echo
echo "Skeleton generated."
echo " cd ${name} && cmake -B build && " \
"make -C build -j bench && build/bench"
echo "You may also need to change your CPU scheduler:"
echo " sudo cpupower frequency-set -g performance"
}

if [[ "$2" == "" ]]; then
echo "Missing project name"
echo
print_help
exit 1
fi

if [[ -e "$2" ]]; then
echo "File \"$2\" already exists"
exit 1
fi

if [[ "$1" == "bin" ]]; then
new_bin "$2"
elif [[ "$1" == "bench" ]]; then
new_bench "$2"
else
echo "Unknown type: $1"
echo
print_help
exit 1
fi

简易内核开发环境

近期尝试了一下写 Linux 内核代码,于是把折腾过程记录一下,方便以后参考。本文默认使用 x86_64 架构以及 Linux 作为宿主系统。

使用 QEMU 运行 Linux 内核

在开始写代码之前,我们需要先准备好模拟器用于运行 Linux。我这里用了QEMU,你也可以用 VirtualBox 之类的虚拟机。一般来说,我们需要一个内核可执行文件(内核本体)和一个 initramfs 镜像(提供用户态程序)。当内核被加载后,它会自动载入 initramfs 镜像,并执行其中的/init程序。由于这一节的重点是 QEMU 配置,所以我直接使用宿主机的内核和 initramfs。以我的 Archlinux 系统为例,内核文件是/boot/vmlinuz-linux,initramfs 文件是/boot/initramfs-linux.img。使用以下命令启动 QEMU,按Ctrl-A x退出。

1
2
3
4
5
6
7
qemu-system-x86_64 \
-kernel /boot/vmlinuz-linux \
-initrd /boot/initramfs-linux.img \
-nographic -append "console=ttyS0" \
-m 512 \
--enable-kvm \
-cpu host
  • -kernel 指定内核可执行文件。
  • -initrd 指定 initramfs disk 镜像文件。
  • -nographic -append "console=ttyS0" 禁用视频输出并使用串口作为终端。
  • -m 512 设定内存。
  • --enable-kvm 使用KVM。
  • -cpu host 使用宿主机的 CPU 特性。

你应该能看到一些系统启动的信息以及无法挂载根分区的报错,这是正常现象,因为我们没有提供任何磁盘文件。你应该可以进入一个紧急修复 Shell, 执行一些简单的如 ls cd 之类的命令。

Haskell 简易指南

安装

用任何你喜欢的方法安装 Glasgow Haskell Compiler (a.k.a. GHC)。Cabal 之类的
依赖管理系统就用不着了。 因为我也不会用。 保证能够执行ghcghci命令就行。

GHCi基础

首先,把以下文件保存成helloworld.hs

helloworld.hs
1
foo = "hello, world"

然后执行ghci helloworld.hs,然后在>提示符后输入foo并回车

1
2
3
4
5
6
GHCi, version 8.6.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main ( helloworld.hs, interpreted )
Ok, one module loaded.
*Main> foo
"hello, world"
*Main>

你可以使用:r来重新载入文件,也可以使用:l <文件名>来载入代码。

编写一个简易的Chrome扩展

时隔半年的毫无诚心的流水帐作品。
假设读者有基础的Javascript能力。

起因

常去的某资源站的某资源发布者喜欢把重要的内容加上花里胡哨的特殊效果并藏在页面的角落里。
虽说要尊重资源的发布者,不过这种给人添堵的行为实在令我感到不爽,于是研究了一下Chrome的扩展程序(Extension)。

基本思路

要干的事情有两件:

  1. 将内容移到页面的显著位置
  2. 去掉辣眼睛的特殊效果 好吧,其实这条并不重要,毕竟内容已经被移到显著位置了

很自然的,直接用Javascript操纵DOM树即可实现希望的效果。
那么要怎么自动载入脚本呢?