海上的宫殿 - 网络
type: channel
link: https://www.soha.moe/category/networking/
items: 玩下认证门户的RFC标准
items: IPv6真的每个地址都能用吗
items: BIRD 与 BGP 的新手开场
items: 业务逻辑丢前端，很强
items: 刚才抓了三段浙江电信插广告的脚本
items: 我重新鼓捣了我的博客！
items: 找呀找呀找红包：soha的红包
items: 让OpenWRT完美适应Hyper-V
items: ngrok——穿透内网必备
items: 加了SSL证书以及把服务器迁回了自己家

玩下认证门户的RFC标准
type: item
date: 2024-03-22T22:39:00+08:00
description: 认证门户（Captive Portal）是生活中非常常见的上网准入方式。当我们连上一个开放式（不需要密码即可连接）的 Wi-Fi 接入点以后，几乎都不能直接访问互联网，而是需要在一个网页上进行一些认证后才可以访问，这就是认证门户。 从这种 Wi-Fi 接入点的准入方式来说，我们很容易就发现一个问题：需要访问网页才能让用户开始准入认证，但怎么才能让用户去访问呢？目前通行的一种做法是直接劫持 DNS 请求或者 HTTP 请求，重定向到认证页面。这种做法在 HTTPS 时代之前很容易做到，但是 HTTPS 时代之后就遇到了困难：由于认证门户并没有用户访问的网站的证书，要劫持用户就势必要用假的证书来进行，这样一来二去也会给用户带来信任不安全证书的坏习惯。 当然，现在的系统也都有自己的做法。比如 Windows 就会尝试用 http 连接 www.msftconnecttest.com，如果请求被重定向了，那么就会弹出页面让用户进行登录。这虽然解决了一部分问题，但是怎么看怎么不清真对吧，所以在 2015 年，RFC 7710 规定了一种方式：如果 DHCP 或 RA 在指定的 option 中发送了一个 URL，那么就引导用户前往该页面进行认证。 RFC 7710 看起来确实解决了一些问题，但是如果用户此前已经登录，其实是没必要再次登录的。这样系统还是绕不开一次互联网连通性的测试，当然 DHCP 服务器可以在通过认证的情况下不发送有关 option，然而 DHCP 服务器并不一定和计费系统是耦合的，做这种耦合也是复杂且不合适的。所以 capport 工作组设计了一套认证门户的标准，也就是 RFC 8908 和 RFC 8910（代替 RFC 7710）。 我了解到 capport 工作组的这些内容，是因为前两天名为菜色狼的群友去了澳门，在澳门线下赌场看完性感荷官在线发牌之后回到了他下榻的喜来登酒店，连上 Wi-Fi 后发现了名为“到期时间”的内容。 一开始我猜测是 DHCP 租约到期时间，但是菜色狼说之前在家里和别的地方都没见过，于是猜测是某种标准，我便顺藤摸瓜找到了上面提到的两个 RFC。 RFC 8908 规定了认证门户对客户端提供一些信息的 API 格式，API 返回格式为 JSON 对象，IANA 也维护了一个注册表来登记可用的字段。目前只有随着 RFC 发布的这几个，其中 captive 字段是必须包含的： captive: boolean 表示用户是否需要登录。 user-portal-url: string 描述了用户完成准入所需访问的页面，也是之前 RFC 7710 中规定的 URL。 venue-info-url: string 描述了网络运营者想向用户展示的内容（例如地图、航班信息等）。 can-extend-session: boolean 表示用户当前的会话是否可以被延长（时间、流量等），这个字段可以让系统在时间或流量将要耗尽的时候让用户访问 user-portal-url 重新认证。 seconds-remaining: number 描述了用户当前会话的剩余时间。 bytes-remaining: number 描述了用户当前会话的剩余流量（字节数）。 其中菜色狼看到的“到期时间”就是 seconds-remaining 带来的。 RFC 8910 则是替代了之前的 RFC 7710，将 URL 的定义改成了 RFC 8908 中提到的 API 端点，同样也有 3 种通告方式： DHCPv4 Option 114 DHCPv6 Option 103 IPv6 Router Advertisement Option 37 有了这两个 RFC，认证门户上网准入的流程就是这样的了： 连上网络、从 DHCP/RA 获得地址的同时知道认证门户 API 的地址。 系统请求 API，得知设备当前的准入状态，如果需要认证则让用户访问 user-portal-url。 设备已经准入，根据 API 返回的信息选择性地进行一些信息展示。 相比劫持用户的连接、系统自己探测这些做法之外，就清晰和明确很多，也安全很多了。 而且这样一来，只需要提供一个 API 地址并返回规定的内容，并不需要一个真实的认证门户就能复现，折腾的劲儿也就上来了。接着我创建了这样一个 PHP 文件： <?php header('Content-Type: application/captive+json'); echo json_encode([ 'captive' => false, 'venue-info-url' => 'https://jin.sh', 'seconds-remaining' => 4555739950 - time(), 'bytes-…

IPv6真的每个地址都能用吗
type: item
date: 2021-07-08T22:04:00+08:00
description: TL;DR: IPv6 子网内第一个地址是任播地址，没有需求，最好别用。 在网上冲浪的时候，经常看到过类似“IPv6 取消了子网号和广播号，所有地址都能用”这样的言论。也经常看到有人给自己的主机或路由器配上形如 2001:db8:1:2:: 的地址。那么，IPv6 真的每个地址都能用吗？ 首先我们先限制一下讨论的范围，要去除各种特殊的地址，例如未指定地址 ::/128、本地回环地址 ::1/128、链路本地地址 fe80::/10 还有多播地址 ff00::/8 等，因为这些地址大家都知道有特定含义、不能乱用。这里说的都是一个普通的单播地址，即全球单播地址（Global Unicast Address，目前是 2000::/3）或者唯一本地地址（Unique Local Address，fc00::/7）范围内的子网的地址。 接着用最近流行的句式讲结论：能，但不是完全能。 诚然，IPv6 中没有 IPv4 中子网的第一个地址是网络号不能用、最后一个地址是广播号不能用的规定。但在规定 IPv6 地址结构的 RFC 4291 中，介绍了一种特别的任播地址——子网路由器任播地址（Subnet-Router Anycast Address） 。这个地址似乎一直被人忽略，也很少有人提，所以知道的人并不多。这个地址就是子网的第一个地址，例如 2001:db8:2:33::/64 这个子网（范围为 2001:db8:2:33:: 到 2001:db8:2:33:ffff:ffff:ffff:ffff）中的子网路由器任播地址就是 2001:db8:2:33::，2001:db8:3:4:5:6:7:8/125 这个子网（范围为 2001:db8:3:4:5:6:7:8 到 2001:db8:3:4:5:6:7:f）中的子网路由器任播地址就是 2001:db8:3:4:5:6:7:8。 如果了解任播（anycast）的概念应该知道，任播是一组主机共享一个地址。对于一个分组，只有这一组主机中的一台会收到，然后做出一定的响应。子网路由器任播地址就是给需要和子网内任意一台（不是指定的一个，也不是所有的）路由器通讯这种场景所保留的。因此这个地址也是有特殊含义的，应当在特定情况下使用，而不是随意使用。 目前很多系统都支持子网路由器任播地址，例如 Linux。Linux 会在 IPv6 转发处于开启状态的时候，自动绑定上机器目前所有子网的子网路由器任播地址。虽然只有路由器才会转发 IPv6 报文，但是有些时候（尤其是我们这些网络技术爱好者），子网内某些机子很可能会打开它，例如需要给 Docker 配上 IPv6 支持的时候。这样的情况下，如果你想通过子网内的第一个地址访问路由器，就有可能会变成访问了你这台 Docker 主机。当然，你可以在网络设备（如交换机）上设置规则来限制除了你指定的路由器之外的主机响应子网路由器任播地址的邻居请求（Neighbor Solicitation）信息，但是你不应该在完全不知道这个知识去使用子网内的第一个地址。 另外，因为/127 大小的子网只有 2 个、/128 大小的子网只有 1 个地址。因此子网路由器任播地址不会在这两个尺寸的子网内起作用。说到这个也是很有趣的：最初，RFC 3627 以这个理由不让大家在路由器之间使用/127 大小的子网，因为这样的子网只有两个地址，第一个地址同时属于两台路由器，那就只有一个地址提供给单独一个路由器了。显然/127 大小的子网做路由器间互联是最合适的，因为方便计算且只有两个地址。于是后来 RFC 6164 要求子网路由器任播地址不能作用在/127 大小的子网中，这样就可以在路由器之间用/127 大小的子网互联了。原来的 RFC 3627 也在第二年被 RFC 6547 废除了。

BIRD 与 BGP 的新手开场
type: item
date: 2020-06-21T17:53:00+08:00
description: 本文同步发布于 GitHub，如有问题、意见、建议，请移步 GitHub issue。 我本来是一直不想写这个这类文章的，因为我一直认为动态路由（包括但不限于 BGP）这玩意儿基本都是学习了计算机网络基础知识的人玩的。这些人大都有足够的阅读、学习经验与能力，根据 BIRD 的官方文档也都能写出基本正确、可用的配置。而且教程往往会导致更多的新手入坑，我并不是很希望什么都不会的人在没有前置知识储备的基础下来研究这个，所以一直没动笔。 但是在我对入坑的新手的行为观察下来，好像有很多人只是想拥有自己的 ASN 然后实名上网，并不想、或没时间对计算机网络、对 BIRD 的配置文件进行深一度的研究和学习，亦或者是因为语言问题，没有去阅读文档。配置文件只是拿别人放出来的进行拼凑（如某些个人博客，和 Vultr 的样例），知其然而不知其所以然，也造成了很多错误的理解。出于这些原因，我还是动笔写下了这篇文章，希望能为新手留下尽量正确的理解。 话虽如此，我还是希望新手能在学习一部分计算机网络的基础后再来，不然有些部分可能会理解困难。 以及建议学习的话选择开几台虚拟机，或者在 DN42（一个世界性的很大的实验性互联网）上进行试验。只有在不满足于在本地或 DN42 实验的情况下，想要真真正正的自己当 ISP，才申请、租用互联网上的 ASN 和 IP 地址资源。 BIRD 与 BGP 的新手开场 版本：1.0-20220806 本文以 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 License 进行授权。 本文中使用的 BIRD 版本为撰写此文时的最新版，BIRD 2.0.7。目前 BIRD 1.x 和 2.x 同时在维护，区别是 1.x 中 IPv4 和 IPv6 协议是分开的（bird 和 bird6），而 2.x 将两部分代码合并在了一起且引入了更多功能。但是 1.x 本身也是落后技术终将被淘汰，所以我推荐使用 BIRD 2.x。两个版本的语法并无差别，无非就是 2.x 在和路由表相关的操作的时候，需要指定特别的协议，如 ipv4; ipv6;。 本文追求的是为有心学习的人提供一个更容易达到的起点。如果只是为了最简单的装逼或者说这篇文章完全看不懂，建议还是别看下去了，可能蔡老师的 RouterOS 版本更适合你。 本文因为是 BIRD 与 BGP 的快速起步，因此不会介绍 BGP 协议，也只会介绍实践部分中用得到的 BIRD 配置，并稍微扩展介绍一些其他 BIRD 的功能，更多的内容则建议在阅读完本文后试着去阅读官方文档，以更深入地理解。 BIRD 官方也提供了一些样例，可以去 BIRD 的 GitLab Wiki 查看。 正文 什么是 BIRD BIRD 的基本语法 杂项 变量与常量 操作符 分支 过滤器和函数 过滤器 filter 函数 function 过滤器写什么呢 路由属性 协议实例 频道 channel 协议 protocol 协议模板 template 杂七杂八的东西 更多配置 控制台 实践中学习 结语 附录 BIRD 全局选路规则 BIRD BGP 协议选路规则 BIRD 的包含（~）操作符 常用的各种配置 公网上约定俗成的最小前缀 Bogon Prefixes and ASNs 与 Vultr 的 BGP session 与 HE TunnelBroker 的 BGP session 1 什么是 BIRD BIRD 是一个实现多种动态路由协议（如 OSPF、BGP、RIP 等）的软件，相似的软件有 FRR（Quagga）、MRT。在 BGP 玩家常用的软件中，BIRD 因其内存占用小、管理方便大受欢迎。 在 BIRD 中，有一个存储了从各个协议收到的路由（包括静态路由）的 RIB（Route Information Base，路由表），经过选路规则的挑选，产生最优的一条路由，这条最优的路由会被写入 FIB（Forward Information Base，转发表）中，导出给系统（如 Linux 内核）中的转发表，这样发到该路由器的流量就能被继续转发了。 注：在高阶玩法中可以使用多个 RIB，在协议中可以指定其使用哪个 RIB，在 BIRD 中也可以指定 RIB 对应的是内核中的哪个 FIB。为了简洁明白，本文只使用 BIRD 的默认 RIB，和内核的默认 FIB。 2 BIRD 的基本语法 和 Juniper、Cisco 等路由器，或 FRR（Quagga）等路由软件不同，写 BIRD 的配置文件就像是在写程序，如果你是个程序员，那么上手应该会很快。正因如此，它也有着和常见编程语言所类似的语法。下面则是一些基础语法。 杂项 用 /* */ 包起来的内容是注释…

业务逻辑丢前端，很强
type: item
date: 2017-03-02T12:25:00+08:00
description: “教育系统很多bug都来自业务逻辑丢前端，以及表单数据处理不严格。” —— Soha King 0x00 无关的背景介绍 又到了一学期一度的选修课选课时间！已经高二下半学期的Soha将迎来最后一期选修课。高一刚入学的时候选了金老师的某课程，然而之前那个学期并没有开课。这一次听说我们班大部分同学选了这节课，我心里也有点痒。（毕竟这是我们的信息技术任课老师，超可爱） 0x01 问题的重现过程 我尝试选择金老师的这门课程。 尴尬……都怪学校当年不开课。 我顺手在“选课”上右键审查元素。 很强，直接把这种东西丢在前面。然后我看了看Network……再点击选课后并没有任何的请求。不过想想也是，除了一个confirm后的doPostBack，没有其他的xhr请求了。 于是我把onclick里面的语句修改了一下（其实直接删掉也没毛病）。 然后再点一次选课。 轻松加愉快。 0x02 Soha的解决方案 虽然没人会处理这种bug 后端加个判断，是否选过这门课。

刚才抓了三段浙江电信插广告的脚本
type: item
date: 2016-05-08T10:52:00+08:00
description: 有空研究一下

我重新鼓捣了我的博客！
type: item
date: 2016-02-21T19:33:00+08:00
description: 今天本来想调一下原来的bootstrap的ui的，结果被我调！炸！了！ 索性一火重新用Materialize写了一个看起来像是Material Design的UI（因为我懒得去看MD的规范） 顺便开启了安全的HTTPS访问。 博客改名了，也麻烦一下各位朋友把友链的名称改成潜入海底。 然后之前那个博客程序也是很老的了，是我在Typecho 0.x（几来着？我忘了）的基础上自己二次开发的。 现在我把博客程序换成了Typecho官方最新版本。 欢迎来访～

找呀找呀找红包：soha的红包
type: item
date: 2016-02-08T18:00:00+08:00
description: 新年到了，身边的朋友都在发红包，几个it圈子里的朋友也做出了找红包的页面。我也花了十几分钟，做了一个找红包的页面。 http：//hb.lohu.info/redBag.php 由于红包有效期是24小时，所以将在2016年2月8日晚上六点(CST)左右公布答案 下面公布答案（解出来的人不多，早知道红包发多一点了） 第一个 点击我要红包。咦？怎么没有红包？好的，我们来看看源码。 （略） 我要红包 （中略） function getHongBaoKouLing(){ $.ajax({ type: 'POST', url: '/hongBao.php', data: { 'year': '2015' }, success: function(data){ console.log(data); alert(data.return); }, dataType: "json" }); } $("#getButton").bind('click',function(){ getHongBaoKouLing(); }); （略） 看起来点击按钮就会调用getHongBaoKouLing()这个函数，这个函数显然是一个POST请求……一眼戳中'year':'2015'，今年明明是2016年了呀！ 到console里重新定义这个函数 function getHongBaoKouLing(){ $.ajax({ type: 'POST', url: '/hongBao.php', data: { 'year': '2016' }, success: function(data){ console.log(data); alert(data.return); }, dataType: "json" }); } 现在再点击按钮，就可以得到8位口令啦！ 0.10元1个，共50个，领走16个（有人说我这么没诚意orz） 第二个 第二个可能稍微有点难找。很多人想到了看cookies。的确有一个名为hongBao的cookie。 但是只有4位数，和我们想要的8位数对不上啊。会藏在哪里呢？这时候回到elements看源码，css里面原来也藏着一点东西！有几个注释…… 分别是8,1,5。还少一位……在最后一个注释的position前面还有一个2！按顺序拼凑加上cookies里面的4位。就是我们要的口令！ 0.66元，共16个，领走3个 第三个 第三个要找到真的是很需要细心的，也很简单。只要使用我提供的入口页面http：//hb.lohu.info/redBag.php再盯牢Network就行了。（没找到的同志们，不会觉得我给的地址是redBag.php却跳转到index.php很奇怪吗？） redBag.php这个回应header里有一个Set-C00kie，第一个=后面显然是base64加密的一段东西。解密，得到8位口令。 0.88元，共10个，领走2个 再次祝大家新年快乐！

让OpenWRT完美适应Hyper-V
type: item
date: 2016-01-09T19:06:00+08:00
description: -1 保持更新 请注意，本文中自行编译的方法已经不再被建议使用。第一点，自己编译可能会遇到一些奇怪的事情，同时也会浪费时间；二则是现在已经有了更好的解决方案。 OpenWRT 的官方 x86 版本现在自带了 Hyper-V 的支持，在官方页面直接下载 x86/64 版本的磁盘映像就可以直接使用第一代 Hyper-V 虚拟机挂磁盘启动了。因为官方给的磁盘映像是仅 MBR 的，如果想要使用第二代虚拟机（UEFI 模式）启动，请参考《构建 UEFI 启动的 OpenWrt 磁盘映像》来构建一个 UEFI 启动的磁盘映像。 Project LEDE他们说自己是Reboot了OpenWRT社区。而且很多用OpenWRT的也都升级到了LEDE。LEDE的x86_64版本是直接支持Hyper-V的，可以直接下载官网预编译版本而不用自己编译。因此建议大家使用LEDE的x86_64版本，本文中的方法仅用于学习借鉴。谢谢。 附上一张LEDE的x86_64的官方预编译版本在Hyper-V上的表现。 0 为什么我会折腾这个 自己在国内放了台服务器，线路什么的都是自己拾掇的。因为丢在自己家里，那条线路也是肩负着我家出网的任务。一时兴起乘着续费线路的机会，打算试试软路由，就搞了个软路由。 首先我根据一篇文章，Hyper-v 安装 OpenWrt_x86 版教程(03.14更新) 在Hyper-V上装好了OpenWRT。 正当我兴奋的时候，我发现测速结果不太对劲。上传下载都只有20Mbps左右。和我的100Mbps相差甚远。看起来像是OpenWRT不支持Hyper-V的网卡，我一直搞不懂这是为什么，后来我闲逛的时候看到了一个贴子：Hyper-V安装Open-WRT的问题。于是我大概知道了为什么我的Hyper-V上的OpenWRT速度会如此坑爹。（看起来我的情况还比这个发帖人好一些哈哈哈） 我马上开始着手倒腾一个适合Hyper-V的OpenWRT。 1 准备工作 首先先get一个Linux Server，然后 git clone git://git.openwrt.org/15.05/openwrt.git 注意一些依赖包，我准备安装了以下包，如果还有别的依赖没安装，make前是会进行依赖检查的 sudo apt-get install build-essential openssl unzip libncurses5-dev zlib1g-dev libssl-dev subversion make过程中经常会从网上下载需要的东西，大部分来自aws，情况大家都是知道的，所以自己准备好proxychains或者vpn等避免下载失败所导致的make中止。 10 修改 修改/package/kernel/linux/modules/virtual.mk，在最后加入下面的内容，添加让Linux内核支持Hyper-V的驱动。 # # Hyper-V Drivers. # define KernelPackage/hyperv-balloon SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) TITLE:=Microsoft Hyper-V Balloon Driver KCONFIG:= \ CONFIG_HYPERV_BALLOON \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/hv/hv_balloon.ko AUTOLOAD:=$(call AutoLoad,06,hv_balloon) endef define KernelPackage/hyperv-balloon/description Microsofot Hyper-V balloon driver. endef $(eval $(call KernelPackage,hyperv-balloon)) define KernelPackage/hyperv-net-vsc SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) TITLE:=Microsoft Hyper-V Network Driver KCONFIG:= \ CONFIG_HYPERV_NET \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/net/hyperv/hv_netvsc.ko AUTOLOAD:=…

ngrok——穿透内网必备
type: item
date: 2015-05-23T20:25:00+08:00
description: 内网是个多么奇怪的东西，所以为了穿透内网，有很多软件，像花生壳内网版，nat123之类。但他们大多不免费。现在好了有这么一个开源的玩意儿——ngrok，一切都变得简单。 首先去ngrok官网(https://ngrok.com/，貌似被GFW认证，大家可以去https://www.tunnel.org.cn/)下载ngrok。平台应该是没有区别的，我是Windows x64版本。（Linux配置方式与本文相同） 准备好以后只要解压到一个地方，没错就这么简单。 接下来就直接用命令行就行啦！让我们来试试转发80端口 打开命令提示符，输入 ngrok http 80 接下来你可以得到一个地址，如上，我是 http://9621c03a.ngrok.io/ 访问就可以看见啦 你也可以试试转发tcp，但是需要在官网注册账号。命令是 ngrok tcp port 有一个问题就是ngrok的服务器的访问速度不够快，接下来，我就告诉大家一个国内的ngrok服务器，就是Tunnel (https://www.tunnel.org.cn/，要求ngrok为1.7版本) ngrok已经准备好了，接下来在https://www.tunnel.org.cn上下载配置文件，你可以按照自己的需求下载不同地方节点。 我选择了美国节点，接下来就把这个配置文件放在和ngrok同根的目录下。然后在命令行里输入 ngrok -config ngrok.cfg -subdomain domain port 执行就可以啦 接下来访问这个地址试试，成功√，速度显然比官方的快 你也可以试试tcp，我就不演示了，命令如下 ngrok -config ngrok.cfg -proto=tcp port 享受你的ngrok吧！

加了SSL证书以及把服务器迁回了自己家
type: item
date: 2015-05-19T23:52:00+08:00
description: 所以https://lohu.info也是可以访问我的博客的（其实主要是为了绕开被电信ban的80端口）感谢StartSSL的服务！ 今天还是cyy同学生日，祝他生日快乐！