AliYun 配置 TunnelBroker IPv6 隧道

流程

  1. 编辑 /etc/sysctl.conf,修改以下条目。
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
  1. 执行 sysctl -p 刷新设置文件
  2. 写入配置信息至 /etc/network/interfaces
auto he-ipv6
iface he-ipv6 inet6 v4tunnel
        address [客户端 IPv6 地址]
        netmask 64
        endpoint [隧道服务器 IPv4 地址]
        local [本机 IPv4 地址]
        ttl 255
        gateway [隧道服务器 IPv6 地址]
  1. 执行 ifup he-ipv6 启用隧道

故障

  1. add tunnel sit0 failed: No buffer space available
    隧道已经存在,执行 ip tun del he-ipv6 删除已经存在的隧道。
  2. add tunnel "sit0" failed: No buffer space available
    系统 IPv6 被禁用或者未更新配置文件,检查 /etc/sysctl.conf 中有无禁用 IPv6 的命令

OCServ Netflix 策略路由

背景

Netflix 账号全球通用,流媒体内容取决于用户 IP 地址来源区域。通常来说,“解锁” Netflix 外区服务有两种方式,分别是全局代理和智能解析。前者最稳定但会影响其他应用的访问速度,后者较灵活,但配置过程繁琐,不适用于全平台。本方案通过配置策略路由,极大降低了对其他网络服务的影响并同时具有全局代理的稳定性。

分析

Netflix 采取了多种方式进行代理检测,包括但不限于 IP 地址检测与 DNS 解析比对。其中 DNS 解析测试服务运行于运用了 Anycast 技术的 AWS EC2 上。因此最保险的方法是路由全部 NetflixAWS 的 IP 段。

提取

使用正则表达式对 IPv4 地址段进行提取。
[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}/[0-9]{1,3}

使用一段简单的 C 程序将地址段整理成 [IP]/[子网掩码] 的形式。

#include "bits/stdc++.h"
int main()
{
    freopen("aws.txt", "r", stdin);
    freopen("res.txt", "w", stdout);
    int a, b, c, d;
    int a1, b1, c1, d1;
    while(~scanf("%d.%d.%d.%d", &a, &b, &c, &d))
    {
        a1 = 255;
        b1 = b == 0 ? 0 : 255;
        c1 = c == 0 ? 0 : 255;
        d1 = d == 0 ? 0 : 255;
        if (d1 != 255)
            printf("%d.%d.%d.%d/%d.%d.%d.%dn", a, b, c, d, a1, b1, c1, d1);
    }
    fclose(stdin);
    fclose(stdout);
    freopen("res.txt", "r", stdin);
    freopen("final.txt", "w", stdout);
    char str1[100], str2[100];
    scanf("%s", str1);
    while(~scanf("%s", str2))
    {
        if (strcmp(str1, str2) != 0)
        {
            printf("%sn", str1);
            memcpy(str1, str2, sizeof(str1));
        }
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

然后进行人工整理与去重至两百条以内,并加上 route = 头部,得到最终的配置片段。

# Netflix
route = 23.246.0.0/255.255.0.0
route = 37.77.0.0/255.255.0.0
route = 45.57.0.0/255.255.0.0
route = 64.120.128.0/255.255.0.0
route = 66.197.128.0/255.255.0.0
route = 69.53.224.0/255.255.0.0
route = 69.53.225.0/255.255.0.0
route = 108.175.32.0/255.255.0.0
route = 185.2.220.0/255.255.0.0
route = 185.9.188.0/255.255.0.0
route = 192.173.0.0/255.255.0.0
route = 198.38.0.0/255.255.0.0
route = 198.45.0.0/255.255.0.0
# AWS
route = 13.0.0.0/255.0.0.0
route = 18.130.0.0/255.0.0.0
route = 23.20.0.0/255.255.0.0
route = 27.0.0.0/255.0.0.0
route = 34.192.0.0/255.0.0.0
route = 35.153.0.0/255.0.0.0
route = 43.250.192.0/255.255.255.0
route = 43.250.193.0/255.255.255.0
route = 46.51.128.0/255.255.0.0
route = 46.137.0.0/255.255.0.0
route = 50.16.0.0/255.255.0.0
route = 50.18.0.0/255.255.0.0
route = 50.19.0.0/255.255.0.0
route = 50.112.0.0/255.255.0.0
route = 52.0.0.0/255.0.0.0
route = 52.46.64.0/255.0.0.0
route = 54.64.0.0/255.0.0.0
route = 63.32.0.0/255.255.0.0
route = 64.252.64.0/255.255.255.0
route = 67.202.0.0/255.255.0.0
route = 70.132.0.0/255.255.0.0
route = 71.152.0.0/255.255.0.0
route = 72.21.192.0/255.255.255.0
route = 72.44.32.0/255.255.255.0
route = 75.101.128.0/255.255.255.0
route = 79.125.0.0/255.255.0.0
route = 87.238.80.0/255.255.255.0
route = 96.127.0.0/255.255.0.0
route = 99.79.0.0/255.255.0.0
route = 99.80.0.0/255.255.0.0
route = 100.20.0.0/255.255.0.0
route = 100.24.0.0/255.255.0.0
route = 103.4.8.0/255.255.255.0
route = 103.8.172.0/255.255.255.0
route = 103.246.148.0/255.255.255.0
route = 103.246.150.0/255.255.255.0
route = 107.20.0.0/255.255.0.0
route = 122.248.192.0/255.255.255.0
route = 143.204.0.0/255.255.0.0
route = 172.96.97.0/255.255.255.0
route = 172.96.98.0/255.255.255.0
route = 174.129.0.0/255.255.0.0
route = 175.41.128.0/255.255.255.0
route = 175.41.192.0/255.255.255.0
route = 176.32.64.0/255.255.255.0
route = 176.32.96.0/255.255.255.0
route = 176.32.104.0/255.255.255.0
route = 176.32.112.0/255.255.255.0
route = 176.32.120.0/255.255.255.0
route = 176.32.125.0/255.255.255.0
route = 176.34.0.0/255.255.0.0
route = 176.34.32.0/255.255.255.0
route = 176.34.64.0/255.255.255.0
route = 176.34.128.0/255.255.255.0
route = 177.71.128.0/255.255.255.0
route = 177.72.240.0/255.255.255.0
route = 178.236.0.0/255.255.0.0
route = 184.72.0.0/255.255.0.0
route = 184.72.64.0/255.255.255.0
route = 184.72.128.0/255.255.255.0
route = 184.73.0.0/255.255.0.0
route = 184.169.128.0/255.255.255.0
route = 185.48.120.0/255.255.255.0
route = 185.143.16.0/255.255.255.0
route = 203.83.220.0/255.255.255.0
route = 204.236.128.0/255.255.255.0
route = 204.236.192.0/255.255.255.0
route = 204.246.160.0/255.255.0.0
route = 205.251.192.0/255.255.0.0
route = 207.171.160.0/255.255.255.0
route = 207.171.176.0/255.255.255.0
route = 216.137.32.0/255.255.255.0
route = 216.182.224.0/255.255.255.0
route = 216.182.232.0/255.255.255.0
route = 216.182.236.0/255.255.255.0
route = 216.182.238.0/255.255.255.0
route = 54.228.16.0/255.255.255.0
route = 54.245.168.0/255.255.255.0
route = 54.248.220.0/255.255.255.0
route = 107.23.255.0/255.255.255.0
route = 52.82.188.0/255.0.0.0
route = 54.222.48.0/255.0.0.0
route = 13.52.0.0/255.0.0.0
route = 18.130.0.0/255.0.0.0
route = 23.20.0.0/255.255.0.0
route = 34.192.0.0/255.255.0.0
route = 34.208.0.0/255.255.0.0
route = 34.224.0.0/255.255.0.0
route = 34.240.0.0/255.255.0.0
route = 34.248.0.0/255.255.0.0
route = 35.153.0.0/255.0.0.0
route = 46.51.128.0/255.255.255.0
route = 46.51.192.0/255.255.255.0
route = 46.51.216.0/255.255.255.0
route = 46.51.224.0/255.255.255.0
route = 46.137.0.0/255.255.0.0
route = 46.137.128.0/255.255.255.0
route = 46.137.192.0/255.255.255.0
route = 46.137.224.0/255.255.255.0
route = 50.16.0.0/255.255.0.0
route = 50.18.0.0/255.255.0.0
route = 50.19.0.0/255.255.0.0
route = 50.112.0.0/255.255.0.0
route = 52.0.0.0/255.0.0.0
route = 54.92.0.0/255.0.0.0
route = 63.32.0.0/255.255.0.0
route = 67.202.0.0/255.255.0.0
route = 72.44.32.0/255.255.255.0
route = 75.101.128.0/255.255.255.0
route = 79.125.0.0/255.255.0.0
route = 96.127.0.0/255.255.0.0
route = 99.79.0.0/255.255.0.0
route = 99.80.0.0/255.255.0.0
route = 100.20.0.0/255.255.0.0
route = 100.24.0.0/255.255.0.0
route = 103.4.8.0/255.255.255.0
route = 107.20.0.0/255.255.0.0
route = 122.248.192.0/255.255.255.0
route = 174.129.0.0/255.255.0.0
route = 175.41.128.0/255.255.255.0
route = 175.41.192.0/255.255.255.0
route = 176.32.64.0/255.255.255.0
route = 176.34.0.0/255.255.0.0
route = 176.34.32.0/255.255.255.0
route = 176.34.64.0/255.255.255.0
route = 176.34.128.0/255.255.255.0
route = 177.71.128.0/255.255.255.0
route = 184.72.0.0/255.255.0.0
route = 184.72.64.0/255.255.255.0
route = 184.72.128.0/255.255.255.0
route = 184.73.0.0/255.255.0.0
route = 184.169.128.0/255.255.255.0
route = 185.48.120.0/255.255.255.0
route = 204.236.128.0/255.255.255.0
route = 204.236.192.0/255.255.255.0
route = 216.182.224.0/255.255.255.0
route = 216.182.232.0/255.255.255.0
route = 216.182.236.0/255.255.255.0
route = 216.182.238.0/255.255.255.0
route = 52.95.110.0/255.255.255.0
route = 205.251.192.0/255.255.255.0
route = 13.32.0.0/255.255.0.0
route = 13.35.0.0/255.255.0.0
route = 13.59.250.0/255.255.255.0
route = 13.113.203.0/255.255.255.0
route = 13.124.199.0/255.255.255.0
route = 13.228.69.0/255.255.255.0
route = 34.195.252.0/255.255.255.0
route = 34.216.51.0/255.255.255.0
route = 34.226.14.0/255.255.255.0
route = 35.158.136.0/255.255.255.0
route = 52.46.0.0/255.255.0.0
route = 52.47.139.0/255.255.255.0
route = 52.56.127.0/255.255.255.0
route = 52.57.254.0/255.255.255.0
route = 52.84.0.0/255.255.0.0
route = 52.212.248.0/255.255.255.0
route = 52.220.191.0/255.255.255.0
route = 52.222.128.0/255.255.255.0
route = 54.182.0.0/255.255.0.0
route = 54.192.0.0/255.255.0.0
route = 54.230.0.0/255.255.0.0
route = 54.239.128.0/255.255.255.0
route = 54.239.192.0/255.255.255.0
route = 54.240.128.0/255.255.255.0
route = 64.252.64.0/255.255.255.0
route = 70.132.0.0/255.255.0.0
route = 71.152.0.0/255.255.0.0
route = 143.204.0.0/255.255.0.0
route = 204.246.164.0/255.255.255.0
route = 204.246.168.0/255.255.255.0
route = 204.246.174.0/255.255.255.0
route = 204.246.176.0/255.255.255.0
route = 205.251.192.0/255.255.255.0
route = 205.251.249.0/255.255.255.0
route = 205.251.250.0/255.255.255.0
route = 205.251.252.0/255.255.255.0
route = 205.251.254.0/255.255.255.0
route = 216.137.32.0/255.255.255.0
route = 18.188.9.0/255.255.255.0

注意

  1. 0.10.5 及之前版本 OCServ 需要修改 src/vpn.h 来支持超过96行(OCServ默认值)但不超过 200 行(Cisco 客户端最大值)的路由表:
    #define MAX_CONFIG_ENTRIES 96,96 改为 200 以上。0.10.6 及之后版本 OCServ 不需要修改,参考 https://gitlab.com/ocserv/ocserv/issues/17

  2. 根据 Cisco 官方文档,no-routeroute 不能同时使用。

    You can specify either split-include or split-exclude, but you cannot specify both options.

效果

对于 Netflix 以及 AWS 服务的流量将全部被路由至远程服务器进行中转,但使用 Netflix 进行观看与下载时所产生的流量会走本地直连。Netflix Open Connect 计划使得 Netflix 与 ISP 进行合作,通过应用 CDN 下沉解决方案,减小 Netflix 与运营商的网络负载和建设成本,而这些 CDN 服务器地址并非 Netflix 所属,而是归属地 ISP 的地址,因此数据是由归属地 CDN 直接传输到本地。

本方案有效降低了服务器的网络负载,对于不同平台具有普适性作用。对于有前置路由的网络场景,可以在路由上直接写入精确的路由表,提高服务运行效率。

OCServ DTLS 连接异常

问题症状

环境:Ubuntu 16.04 x64
版本:OCServ 0.10.11-1build1
今日重置了阿里云 ECS 后,选择从 APT 源直接安装 OCServ 而非从官网手动下载安装,随后便发生了一些诡异事情。
service ocserv start 所启动的 OCServ 服务在 IPv4 网络中进行连接时,尽管网络状态良好,仍然回退到了 TLS 链路。而使用 ocserv 命令直接启动服务却能正常建立 DTLS 连接。
使用 lsof -i:443 检查 443 号端口监听状态时发现,前者会由 systemdocserv-main 共四个进程监听 IPv6 协议类型上的 443 号端口的 UDP/TCP,而后者由 ocserv 共两个进程监听 IPv4 协议类型上的 443 号端口的 UDP/TCP。
查看 /etc/init.d/ocserv 文件发现,OCserv Daemon 在启动时会正确调用位于 /etc/ocserv/ocserv.conf 的配置文件,但却没有根据配置文件中的设定进行监听。

解决方案 1

早在 2016 年便有人指出这个缺陷(现已修复),而阿里云 APT 源中的包版本较老,所以没有修复此问题。

Try to go to “/lib/systemd/system/” and modify the file of “ocserv.service”,
1.use vim to change two lines,
2.Remove the line of “Requires=ocserv.socket”
3.Remove the line of “Also=ocserv.socket”
4.save the file,

execute “systemctl daemon-reload”,
then reload the service “service ocserv start”

  1. 编辑 /lib/systemd/system/ocserv.service,移除 Requires=ocserv.socketAlso=ocserv.socket
  2. 重新加载 Systemd 配置文件:执行 systemctl daemon-reload
  3. 重启 OCServ 服务:执行service ocserv start

服务重启后,DTLS 连接可以正常建立,且未与 OpenVZ-BBR 冲突,至此问题得到了完美解决。

解决方案 2

使用 apt remove ocserv 移除旧版本的 OCServ,从 OCServ 项目官网 下载最新版本的 OCServ,然后手动安装。

在 OI 与 ACM 比赛中进行常数优化

输入输出优化

读取整数

适用于正负整数。
注意:在 C 与 C++ 中函数的求值顺序是不确定的,当多个参数需要调用输入输出挂时,必须引入中间变量。

inline long long LL()
{
    char c;
    bool neg = false;
    while((c = getchar()) < '0' || c > '9')
        neg = c == '-';//等价于 neg = (c == '-'),因为 == 的优先级更高
    int a = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        a = a * 10 + c - '0';
    return neg ? -a : a;
}

输出整数

适用于正负整数。

inline void Out(long long n)
{
    if (n < 0)
        putchar('-'), n = -n;
    if (n >= 10)
       Out(n / 10);
    putchar(n % 10 + '0');
}

前置 ++

使用++i代替i++。不过现在大部分编译器已经会将i++优化为++i了,所以一般不用处理。

关闭同步

由于scanf(), printf()的格式化字符串操作是在运行时解析的,因此取消同步后使用cincout进行处理可以获得更快的速度。
注意:此时不可以再混用scanf()cin, printf()cout

std::ios_base::sync_with_stdio(false);
std::cin.tie(0);

减少循环中不必要的计算

例如,将for循环头部的strlen()的计算引入中间变量,有利于提高程序的运行效率。

循环展开

减少不必要的循环次数。

References