借助IPsec和strongSwan建立隧道并分配IPv6地址

准备

在一年前,我写过一篇文章,介绍利用GRE隧道将一台服务器的IPv6地址“分配”给另一台电脑,令其能访问IPv6网络的方法。
不过那种方法存在一些问题:

  • 不能通过NAT
  • 数据不加密
  • 需要在服务器手动更新IP

于是热爱折腾作死的我研究了一下使用IPsec配合IKEv2对流量进行加密的方法。

服务器与本地均为ArchLinux(Arch大法好),strongSwan软件包可从AUR安装。
服务器需要至少有一个公网IPv4和一段Routed IPv6 Subnet。

Linux环境TCP Socket与Epoll使用备忘

流水帐式地记录了 Linux 下 TCP Socket 通信的方法和基本的 Epoll 使用方法。
没有错误处理。

地址解析

1
2
3
4
struct addrinfo *listen_addr; //存放解析结果。参见`man getaddrinfo`
getaddrinfo("0.0.0.0", "55553", NULL, &listen_addr); // getaddrinfo([主机名],[端口],[hint],[结果])。成功返回 `0`
// ...
freeaddrinfo(listen_addr); //释放资源,返回void

监听

这种方式只能同时处理一个连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int fd = socket(AF_INET, SOCK_STREAM, 0); // int socket(int domain, int type, int protocol); 参见`man 3 socket` 创建文件描述符, 出错返回-1
bind(fd, listen_addr->ai_addr, listen_addr->ai_addrlen);
// int bind(int socket, const struct sockaddr *address,socklen_t address_len);
// 绑定地址,出错返回-1,参见`man 3 bind`
listen(fd, SOMAXCONN);
// int listen(int fd, int backlog(最大队列长度))
// 开始监听,出错返回-1
while (1) {
int new_fd = accept(fd, NULL, NULL);
// accept([fd], [监听地址], [监听地址结构体长度]) 第2,3个参数同bind()
// 接受连接请求,若无请求则阻塞(也有可能是EAGAIN,取决于你需要什么)
// 返回用于和对端通信的新的文件描述符,出错返回-1
// ... handle(new_fd);
close(new_fd); // 关闭文件描述符
}

Linux下建立GRE隧道并获取IPv6地址

虽然HE有提供免费的Tunnelbroker,不过那速度实在不怎么样。于是考虑在有IPv6地址托管主机上建立一个GRE Tunnel。
GRE Tunnel需要有内核模块ip_gre支持。远程主机有一段/64的IPv6,我将其中的一段/80分配给自己的机器。
使用iproute2工具。当然,你自己的机器需要有一个公网IPv4地址。

  1. 服务器的公网IPv4是$server_ipv4
  2. 自己电脑(或者路由器)的公网IPv4是$client_ipv4
  3. 服务器的IPv6段是a:b:c:d::/64
  4. 要分配下去的IPv6段是a:b:c:d:e::/80

服务器配置

脚本如下,需要root,建议用sudo -i

1
2
3
ip tunnel add gre-tunnel mode gre remote $client_ipv4 ttl 64
ip link set gre-tunnel up
ip addr add a:b:c:d:e::1/80 dev gre-tunnel
  • 第一行建立隧道,gre-tunnel是隧道名称,可以按自己喜欢的来,记得其他的也要一起改
  • 第二行激活隧道
  • 第三行分配IP地址

IDEA下建立Forge开发环境的正确姿势

前言

本文作于2014年末,其中记载的方法可能已经过期,请读者谨慎参考
见过不少教程都是基于Eclipse的,而基于IDEA的文章少得可怜,遂决定写此文。
本文通篇基于Linux/IntellijIDEA进行讲解,Windows/MAC/Eclipse用户请自行依葫芦画瓢。

设置Forge工作区

当然,你得首先去MinecraftForge下载一份源代码。我这里用的是最新的forge-1.7.10-10.13.2.1258-src.zip
接着,找个地方建立一个文件夹,这将是你的工程目录,我的叫做Forge1.7.10-1258。然后再在里面建立一个目录,比方说就叫forge-1.7.10-10.13.2.1258-src,把你的Forge源码解压进去。
现在,你的文件夹层次应该看起来是这样的:

Forge1.7.10-1258
└── forge-1.7.10-10.13.2.1258-src
     ├── build.gradle
     ├── CREDITS-fml.txt
     ├── eclipse
     ├── forge-1.7.10-10.13.2.1258-changelog.txt
     ├── gradle
     ├── gradlew
     ├── gradlew.bat
     ├── LICENSE-fml.txt
     ├── MinecraftForge-Credits.txt
     ├── MinecraftForge-License.txt
     ├── README.txt
     └── src

你可以先按自己喜好改动一下build.gradle。比如,我喜欢手动指定一下mappings的版本:

1
2
3
4
5
minecraft {
version = "1.7.10-10.13.2.1258"
runDir = "eclipse"
mappings = "stable_12"
}

接着,cd到forge-1.7.10-10.13.2.1258-src目录下,执行如下两条命令:

gradle -i setupDecompWorkspace
gradle -i ideaModule

然后请耐心等待指令完成,可以去喝杯牛奶睡个觉什么的。

Minecraft Coremod开发杂事记

表示最近时间荒废得厉害,主要都是耗在了Minecraft这款游戏上。
Minecraft的一大魅力在于其几乎无穷的MODs,于是我也小试了一下Mod开发,顺便学习一下Java。于是掉入了万劫不复的深坑
当然,我要做点和加个方块、改个合成表之类的不一样的事。
(教程中不少内容都参考了szszss的博客,在此表示深深的感谢)

基础知识

关于这篇文章,不适合特别特别新的新人,我假设各位读者都有一些基础的编程经验。如果你是入门级别的,在MCBBS论坛的编程开发板块有不少不错的入门教程。
我假设各位读者都具备以下能力:

  • 会安装软件
  • 了解基本的程序流程控制,比如判断、循环等
  • 了解基本的OOP概念,比如类,继承等 (其实这条不是那么重要,Java看多了就自然会了 一个原C程序员如是说
  • 了解命令行、终端的基本使用方法
  • 有方法正常访问国际互联网,如Facebook等
  • 了解基本英语单词(这条似乎也不是那么重要,主要是希望大家能够在遇到问题时不要怕阅读英文资料)
  • (本教程面向Linux用户,Mac用户大同小异,Windows用户自己看着办)

域名注册商更换

昨天折腾了一天,把域名从Godaddy转移到了Name.com
表示基本没遇到什么麻烦,信用卡借用了家长的,付款也很方便。
关键是便宜啊。转入9美刀,续期11美刀,比Godaddy坑爹的18刀便宜太多了啊~
而且还有免费的WHOIS保护啊
优惠码PRIVACYPLEASE超好记有木有!
虽然不是最便宜的但是Name.com的控制台相当美观呐~
结尾吐槽一句:在万网注册的都是真的勇士。

Programming with PTRACE, Part6 - 时间控制

不同的时间计算方法

程序运行会占用一小段时间(废话),事实上,我们有不止一种方法来表示一个程序运行了多长时间。最直观的应该是“墙上时间”,也就是说,你掐个秒表,看看程序从开始到结束用了多长时间。除此之外,还有“用户态时间”和“内核态时间”,这两个时间都是以CPU实际运算的时间,也就是CPU周期,来计数的。“用户态时间”就是程序在用户态执行的时间,包括程序所引用的库中的代码(比如STL),“内核态时间”就是指程序在内核态执行的时间,一般是各种系统调用(比如各种IO操作)。这两种时间和墙上时间的区别在于,因为CPU其实是在多个程序中快速切换的,所以在运行某个程序的时间里,CPU也处理了属于其他进程的任务,而且CPU切换任务也需要一定的时间(真的很短)。如果处于被调试状态,tracer的运行时间也会被计算在内,这些不属于这个进程的时间片也会被计算在这个进程的“墙上时间”里。所以一般以用户态时间和内核态时间的总和作为进程的运行时间。

在Linux系统里有一个叫time的命令可以查看一个命令执行了多长时间。这个命令有两个版本,一个是shell内置的,另一个是独立的可执行文件,可以用type time命令查看。虽然可执行版本功能更强一点,但内置的功能足够,这一点区别可以不管。用法是: time [命令] <参数>。给个例子:

time ffmpeg -i sample.mp4 target.mp3
...
5.42s user
0.10s system
100% cpu
5.520 total