分类 转载分享 下的文章

本文目的是为服务器配置可供多种操作系统访问的 IKEv1/IKEv2 接入,需要支持 Radius 认证;按照本文配置,没有进行流量统计的功能,如果有相关需求,请自行配置 Radius 和 StrongSwan 的 eap-radius 组件。
本文实现的 Radius 认证方式有:
EAP-MSCHAPv2(用户名+密码)、EAP-TLS(证书)、EAP-TTLS(证书)、PEAP(用户名+密码)

已知的问题
PEAP本可以支持两种认证方式:PEAP-EAP-MSCHAPv2(用户名+密码)与PEAP-EAP-TLS(证书)

但 FreeRadius 在PEAP中仅支持PEAP-EAP-MSCHAPv2与PEAP-EAP-TLS必须二选一而不能同时启用。

FreeRadius 推荐且默认为PEAP-EAP-MSCHAPv2,鉴于用户使用PEAP-EAP-MSCHAPv2是主流,且后者替代品丰富,所以放弃对PEAP-EAP-TLS的支持。但出于测试的目的,笔者尝试配置PEAP-EAP-TLS却未能成功。

系统环境
公有云上的 CentOS 7 x86_64(非 OpenVZ),双核,2 GB 内存,SELinux 不开启

配置StrongSwan
说明:不使用 yum 直接安装的原因是在库中的二进制 StrongSwan 的参数配置导致无法通过 OS X 与 iOS 连接

配置环境 & 编译
编译安装默认的配置文件路径为 /usr/local/etc,通过 yum 安装的默认为 /etc/strongswan

yum -y install pam-devel openssl-devel make gcc curl wget
wget --no-check-certificate https://download.strongswan.org/strongswan-5.3.5.tar.gz
tar zxvf strongswan-5.3.5.tar.gz
cd strongswan-5.3.5
./configure --enable-eap-identity --enable-eap-md5 \
--enable-eap-mschapv2 --enable-eap-tls --enable-eap-ttls --enable-eap-peap \
--enable-eap-tnc --enable-eap-dynamic --enable-eap-radius --enable-xauth-eap \
--enable-xauth-pam --enable-dhcp --enable-openssl --enable-addrblock --enable-unity \
--enable-certexpire --enable-radattr --enable-swanctl --enable-openssl --disable-gmp
make && make install
配置证书
需要生成的证书包括根证书(CA)、服务器证书(Server)和客户端证书(Client),客户端证书可用于通过证书认证。

生成根证书
ipsec pki --gen --outform pem > ca.key.pem
ipsec pki --self --in ca.key.pem --dn "C=CN, O=VisionSrv, CN=VisionSrv CA" --ca --lifetime 3650 --outform pem > ca.cert.pem
生成服务器证书
ipsec pki --gen --outform pem > server.key.pem
ipsec pki --pub --in server.key.pem --outform pem > server.pub.pem
ipsec pki --issue --lifetime 1200 --cacert ca.cert.pem --cakey ca.key.pem --in server.pub.pem --dn "C=CN, O=VisionSrv, CN=dev.panic.ml" --san="dev.panic.ml" --flag serverAuth --flag ikeIntermediate --outform pem > server.cert.pem
生成客户端证书
ipsec pki --gen --outform pem > client.key.pem
ipsec pki --pub --in client.key.pem --outform pem > client.pub.pem
ipsec pki --issue --lifetime 1200 --cacert ca.cert.pem --cakey ca.key.pem --in client.pub.pem --dn "C=CN, O=VisionSrv, CN=dev.panic.ml" --outform pem > client.cert.pem
生成 p12 证书可以设置密码,请注意:OS X 无法导入密码为空的 p12 证书
openssl pkcs12 -export -inkey client.key.pem -in client.cert.pem -name "VisionSrv Client Cert" -certfile ca.cert.pem -caname "VisionSrv CA" -out client.cert.p12
复制证书
说明:

(1)如果你希望用户通过用户名 + 密码连接 IKEv2,请将 ca.cert.pem 发送给客户并要求客户安装证书
(2)如果你希望用户直接通过证书登陆,请将 client.cert.p12 发送给客户并要求客户安装证书
(3)如果是 iOS,用户还需要安装 ca.cert.pem
(4)如果是 OS X,用户需要设置 CA 根证书为可信
cp -r ca.key.pem /usr/local/etc/ipsec.d/private/
cp -r ca.cert.pem /usr/local/etc/ipsec.d/cacerts/
cp -r server.cert.pem /usr/local/etc/ipsec.d/certs/
cp -r server.key.pem /usr/local/etc/ipsec.d/private/
cp -r client.cert.pem /usr/local/etc/ipsec.d/certs/
cp -r client.key.pem /usr/local/etc/ipsec.d/private/
配置 ipsec.conf
通过编译安装,ipsec.conf 路径为 /usr/local/etc/ipsec.conf,通过 yum 安装路径为 /etc/strongswan/ipsec.conf

config setup

uniqueids=never 

conn cisco_cert

keyexchange=ikev1
fragmentation=yes
left=%defaultroute
leftauth=pubkey
leftsubnet=0.0.0.0/0
leftcert=server.cert.pem
right=%any
rightauth=pubkey
rightauth2=xauth-radius
rightsourceip=10.31.2.0/24
auto=add

conn cisco_xauth_psk

keyexchange=ikev1
left=%defaultroute
leftauth=psk
leftsubnet=0.0.0.0/0
right=%any
rightauth=psk
rightauth2=xauth-radius
rightsourceip=10.31.2.0/24
auto=add

conn standard_ikev2

keyexchange=ikev2
ike=aes256-sha256-modp1024,3des-sha1-modp1024,aes256-sha1-modp1024!
esp=aes256-sha256,3des-sha1,aes256-sha1!
rekey=no
left=%defaultroute
[email protected]
leftsendcert=always
leftfirewall=yes
leftsubnet=0.0.0.0/0
leftcert=server.cert.pem
right=%any
rightauth=eap-radius
rightsourceip=10.31.2.0/24
eap_identity=%any
dpdaction=clear
fragmentation=yes
auto=add

配置 strongswan.conf
通过编译安装,ipsec.conf 路径为 /usr/local/etc/strongswan.conf,通过 yum 安装路径为 /etc/strongswan/strongswan.conf

charon {

load_modular = yes
duplicheck.enable = no #是为了你能同时连接多个设备,所以要把冗余检查关闭
compress = yes
plugins {
    include strongswan.d/charon/*.conf
    eap-radius {
        servers {
            server-a {
                address = YourRadiusServer
                secret = YourRadiusSecret
                # nas_identifier = ipsec-gateway
            }
        }
    }
}
dns1 = 114.114.114.114
dns2 = 8.8.8.8
# for Windows WINS Server
nbns1 = 114.114.114.114
nbns2 = 8.8.8.8

}

include strongswan.d/*.conf
配置 ipsec.secrets
通过编译安装,ipsec.conf 路径为 /usr/local/etc/ipsec.secrets,通过 yum 安装路径为 /etc/strongswan/ipsec.secrets

: RSA server.key.pem
: PSK "visionsrv"
: XAUTH "visionsrv"
test : EAP "123456"
我们在这里增加了一个测试账号,但在 Radius 认证中并不生效,如果需要使用此认证用于测试或不需要使用 Radius 进行认证,请将 ipsec.conf 中的 rightauth(或 rightauth2) 值改为 eap-mschapv2(eap-radius) 或 xauth(xauth-radius)

注意: 在停用 Radius 认证后,使用本文配置将无法通过客户端证书直接连接 VPN 服务器。如有需要,请自行研究配置方式。 下面是一些直接使用证书认证的参考资料: StrongSwan Android、Windows 身份验证(使用计算机证书)-> IKEv2 Certificate -> rightauth=pubkey StrongSwan Android、OS X、iOS -> EAP-TLS -> rightauth=eap-tls Linux 通过 NetworkManager-strongswan 支持上述所有方式

配置防火墙
本文使用的是 CentOS 7 默认的防火墙 firewalld,如需要 iptables 请查看官方文档或参阅 Google

firewall-cmd --add-port=500/tcp --permanent
firewall-cmd --add-port=500/udp --permanent
firewall-cmd --add-port=4500/tcp --permanent
firewall-cmd --add-port=4500/udp --permanent
firewall-cmd --add-masquerade --permanent
firewall-cmd --reload
启动服务
systemctl start strongswan
systemctl enable strongswan
配置 Radius
安装并配置 FreeRadius

yum install -y freeradius*
echo 'test ClearText-Password := "123456"' >> /etc/raddb/users

配置 Radius 客户端,0.0.0.0 替换为 VPN 服务器地址,123456 替换为您想设置的 Radius 连接密钥

cat >> /etc/raddb/clients.conf < <-EOF
client 0.0.0.0 {

    secret = 123456
    shortname = 0.0.0.0
    nas_type = other

}
EOF
请将 CA 根证书ca.cert.pem放置在/etc/raddb/certs/ca.pem(本项如果不需要通过客户端证书连接可以不配置)

请将服务器证书server.cert.pem放置在/etc/raddb/certs/server.pem

服务器私钥server.key.pem放置在/etc/raddb/certs/server.key

完成后,请执行命令cat /etc/raddb/certs/server.key >> /etc/raddb/certs/server.pem

2016-5-8 更新: 新版 OS X 对用户名+密码不再要求强制校验服务器身份,所以不使用证书登陆可以不配置 RADIUS 证书。

注意
不配置 Radius 服务器证书时 Windows PEAP 连接将弹出提示(提示信息为“信息不足,无法验证服务器”),OS X 将拒绝连接。

需要说明的是,这并不是一般的 Radius 服务器证书配置方法,但出于简单、实用且易于描述的考虑我们这样做以免您产生混淆。

正常的做法是通过通用的 CA 根证书、 CA 私钥、 CSR 文件以及 FreeRadius 内置的私钥为 Radius 服务器生成一个证书。

这样生成的服务器证书可以被 VPN 客户端的 PEAP 判断为合法的服务器并进行连接。

OS X 使用 PEAP-EAP-MSCHAPv2(用户名)和 EAP-TLS(证书)并强制要求校验服务器合法性。

Windows 可以选择使用 PEAP-EAP-MSCHAPv2(用户名)和 EAP-TLS(证书),但配置更自由,更具灵活性。

在本文所述的方法中,因 server.pem 中的私钥是未加密的,所以 eap 配置文件中的私钥密码是不产生作用的。

配置防火墙

Radius 认证端口

firewall-cmd --add-port=1812/udp --permanent

Radius 计费端口(本文不会使用)

firewall-cmd --add-port=1813/udp --permanent
firewall-cmd --reload
客户端配置
说明:

(1)如果你希望用户通过用户名 + 密码连接 IKEv2,请将 ca.cert.pem 发送给客户并要求客户安装证书
(2)如果你希望用户直接通过证书登陆,请将 client.cert.p12 发送给客户并要求客户安装证书
(3)如果是 iOS,用户还需要安装 ca.cert.pem
(4)如果是 OS X,用户需要设置 CA 根证书为可信
OS X
OS X 采用了严格的安全校验措施,IKEv2 连接采用 PEAP(用户名+密码)/EAP-TLS(证书) 模式并必须验证服务器身份,
对服务器校验分两步:(1)校验该服务器证书是否是合法 CA 签发的,(2)校验被连接服务器的被连接域名是否是证书允许的
OS X 要求这两部分必须均校验且通过,Windows 可以选择是否校验以及校验至哪一步。
这意味着为了保证 OS X 正常使用 IKEv2,您必须为 Radius 服务器配置证书。
iOS 与 OS X 的要求相似,本文以 OS X 为例进行说明。
IKEv1
配置位置:系统偏好设置 -> 网络 -> 新建 -> VPN -> Cisco IPsec
服务器地址:在这里输入您的服务器地址
账户名称:在这里输入用户名
密码:在这里输入密码
在鉴定设置 -> 共享的密钥中输入在 ipsec.secrets 中设置的 PSK 预共享密码
IKEv2
配置位置:系统偏好设置 -> 网络 -> 新建 -> VPN -> IKEv2
服务器地址:在这里输入您的服务器地址
远程地址:在这里输入您的服务器地址
在鉴定设置 -> 用户名中输入在 ipsec.secrets 中设置的用户名和密码(通过用户名密码登陆)
在鉴定设置 -> 证书中选择安装的客户端证书(通过客户端证书登陆)
Android
由于 Andorid 的版本众多,配置方法可能不同但大同小异。

IKEv1
说明:您也可以使用 IPSec Xauth RSA 进行连接,但需要安装证书,连接时选择客户端证书,CA 和服务器证书留空

配置位置:设置 -> 其它连接方式 -> VPN -> 添加 VPN
名称:在这里填写任意名称
类型:IPSec Xauth PSK
IPsec 标识符:不更改此项内容
预共享密钥:在这里输入在 ipsec.secrets 中设置的 PSK 预共享密码
此后,在连接时输入您的用户名和密码。

IKEv2
您需要安装 StrongSwan Andorid 版本,具体配置方法详见不同版本的配置方法。

由于该 APP 为官方出品,支持认证方法众多,配置简单,推荐使用。

Windows
说明:鉴于 Windows 支持认证方式较为广泛,本文仅示例最简单的通过 EAP(MSCHAPv2) 与通过本地证书(EAP-TLS)进行认证

Windows 7 以下版本不支持 IKEv2 连接,所有版本均不支持 IKEv1 连接,如有需要请下载第三方组件。
本文配置对于 Windows 7 以上版本的 IKEv2 连接,支持通过 EAP-MSCHAPv2、EAP-TLS、PEAP(部分支持)、EAP-TTLS 认证
本文采用 Windows 10 作为操作示例,其它受支持的 Windows 版本配置与本文类似,请自行研究。
如前文所述,本文对于 PEAP 仅支持 PEAP-EAP-MSCHAPv2(用户名+密码),不支持 PEAP-EAP-TLS(证书)。
有消息称,不同连接方式之间的性能可能存在差异,但笔者并未进行详细的性能测试。
注意:笔者测试 StrongSwan 官方的 Windows 7 配置,但 Windows 7 仍不可连接。 错误提示为 IKE 身份验证凭证不可接受,该问题通常是由于 CA 根证书未安装导致,但 CA 根实际上已经安装。 因此,错误原因不明,该问题仅在 Windows 7 (Windows Server 2008)上被发现,其他未见影响。

IKEv2
配置位置:网络与共享中心 -> 设置新的连接或网络 -> 连接到工作区 -> 使用我的 Internet 连接
Internet 地址:在这里填写服务器地址
确认后,在网络与共享中心 -> 更改适配器设置 -> 选择刚刚添加的 VPN -> 右键选择属性 -> “安全”中“VPN 类型”选择 IKEv2
在这里,我们展示两种方式:

方法一:通过 EAP-TLS 使用证书连接

(1)安装客户端证书 client.cert.p12,设置为可信
(2)在“安全”中选择“Microsoft: 智能卡或其他证书(启用加密)”,在“属性”中选择“在此计算机上使用证书”
(3)完成上述步骤后,可以勾选“通过验证证书来验证服务器身份”,在文本框中输入 VPN 服务器地址
(4)勾选“连接到这些服务器”,在证书列表中选择 CA 根证书(一般在最后一个)后确定
(5)尝试连接到 VPN 服务器即可
说明:用户可以关闭“通过验证证书来验证服务器身份”,但这将降低用户安全性。

方法二:通过 EAP-MSCHAPv2 使用用户名与密码连接

(1)安装 CA 根证书,设置为可信
(2)在“安全”中选择“Microsoft: 安全密码(EAP-MSCHAP v2)(启用加密)
(3)尝试输入账号密码进行 VPN 连接即可。

一、软件说明

    IPsec是虚拟私密网络(*)的一种,用于在服务器和客户端之间建立加密隧道并传输敏感数据之用。它由两个阶段组成,第一阶段(Phrase 1, ph1),交换密钥建立连接,使用互联网密钥交换(ike)协议; 第二阶段(Phrase 2, ph2),连接建立后对数据进行加密传输,使用封装安全载荷(esp)协议。

    其中,第一阶段和第二阶段可以使用不同的加密方法(cipher suites)。甚至,第一阶段ike协议的第一版(ikev1)有两种模式,主力模式(main mode)和积极模式(aggressive mode),主力模式进行六次加密握手,而积极模式并不加密,以实现快速建立连接的目的。

    第一阶段的 ike 协议有两个版本(ikev1/ikev2),不同的开源/闭源软件实现的版本均不同,不同的设备实现的版本也不同。再联系到第一阶段/第二阶段使用的各种不同加密方法,使得 IPsec 的配置有点黑魔法的性质,要么完全懂,通吃; 要么完全不懂,照抄。

二、设备操作系统规格

这里主要介绍了设备/操作系统使用的 ike 版本及其特殊要求。

Linux

    命令行客户端就是 strongswan 本身,因此完美兼容,支持 ikev1/ikev2 和所有加密方法的连接。因此如果用户只使用 Linux 命令行客户端,不使用各种移动设备也不使用 Windows,那么完全没有那么多事。

    但 Linux 的图形界面客户端 NetworkManager-strongswan 目前只支持 ikev2 连接,必须使用证书或 EAP (各种加密方法都支持,包括微软的 MSCHAPv2)进行认证,不支持纯密码(PSK)认证。这并不是 strongswan 的错误,或者技术不行(开源总是走在技术最前沿的,毕竟命令行是支持的),而仅仅是体现一种选择:ikev1 被 strongswan 项目认为是该淘汰的协议,而 PSK 加密被认为是非常不安全的。参考 strongswan 维基 NetworkManager 词条。

Android

    Android 和 Linux 不一样,只支持 ikev1。其它方面和 Linux 一样,甚至有好多种 IPsec * 配置模式可供选择。

IOS/Mac OS X

    它们声明使用的 IPsec 客户端为 Cisco,实际为自己修改的 racoon。它只支持 ike 协议的第一版即 ikev1,可以使用证书或纯密码(PSK)认证,但必须辅之 xauth 用户名/密码认证。

该修改版的 racoon 会优先使用不加密的积极模式,而积极模式是 strongSwan 所不支持的。所以要使用主力模式。

    IOS 6 还有一个「衔尾」故障:它在第一阶段握手时会把数据包拆分成小块(fragmentation),然后「加密」发送。然而这种加密仅仅是声明的,其实并未加密,这就导致 strongSwan 及其它标准服务器端/Cisco 设备无法解密。另外 ikev1 的 fragmentation 插件是闭源的。开源服务器端无法对这些小块进行重组。参考:Cisco * stop working after upgrading to IOS 6

所以产生了一种权宜之计,就是使用小证书(小于 1024,默认一般为 2048),来达到不拆包的目的。但是 Mac OS X 10.7 的更新却对这种方式进行了封杀,学习微软加入了证书验证,小证书直接拒绝。

所幸 strongswan 5.0.2 已经完成了 fragmentation 的开源实现和对 iOS 那个声明加密其实未加密故障的处理:IKE message fragmentation (cisco) + IOS 6.0 Hack for encrypted flaged ike fragmentation packets,该链接中也能找到 strongswan 4 的补丁。

Windows

    微软的差劲只比 iOS 好一点。好处在于它支持了 ikev2,但是只在 Windows 7 以后支持,Vista 之前依然使用 ikev1,坏处在于它的 ikev2 支持非常诡异,指定了 Diffie Hellman group(DH,迪菲-赫尔曼密钥交换组)必须是 modp1024。这是非常少见理论上不应该由系统管理员操心的加密选项:

    在 strongswan 中,定义第一阶段(ike)和第二阶段(esp)加密方法的语法是:

ike/esp=encryption-integrity-dhgroup
第一阶段/第二阶段=加密方法-健壮性认证方法 (后面两项可选)[-DH 组] [-扩展序列号支持模式(RFC4304)]

参考:IKEv2CipherSuites

    Windows 定义了一个可选的选项,导致了我们必须去定义整个第一阶段的加密方法。这样被破解的可能性就提高了。

    其次在于它的 rekey(重连)。IPsec 的认证是有时效的,超过时间会重新认证。这种 CHILD_SA 认证可由服务器发出,也可由客户端发出,一般是由服务器发出。但是 Windows 7 的 ikev2 的表现是,如果你在路由器(NAT)后,收到这种请求会把微软内部的通知代码发出去,代码为 12345, 经过 strongswan 项目侦错后发现这个代码的意思是 ERROR_IPSEC_IKE_INVALID_SITUATION。但是处理不了,它不是 IPsec 标准协议定义过的错误。

于是有两种权宜之计:

    一种是让 Windows 7 来主动 rekey。Windows 7 rekey 的时间大约是 58 分 46 秒,所以要配置服务器 rekey 时间比它长。但是效果非常不好。因为 rekey 是由三个变量控制的,key 的生命周期,key 的边际时间(生命周期前多久进行 rekey),和边际时间误差(rekeyfuzz),误差是不可控的。参考:ExpiryRekey。

    即使能控制 strongswan 这边,Windows 依然是「大约」; 即使两边都能控制,假设服务器延后一秒 rekey,理论上如果连接持续时间足够长,依然能够撞车:58x60+46 次 rekey 后即 146 天后撞车,连一年都没有,在 Linux 服务器对 Windows 服务器这种使用实例中就明显不符合要求。

所以目前只能使用后一种方法即完全禁用服务器端 rekey。

    最后,它的 EAP 认证也非常糟糕。MSCHAPv2 的 eap 身份不是 ikev2 身份(ikev2 身份一般是 EAP 用户名),所以必须在服务器端显式定义 eap_identity 来使用 Windows 7 的 eap 身份。

三、软件的安装

软件的安装很方便,这里我们使用epel仓库里面的yum安装

yum install strongswan 

一条命令就安装好了,下面来查看安装了哪些文件

rpm -ql strongswan

这里我就不展示有哪些内容,下面来看看我们主要使用的配置文件

rpm -qc strongswan

其中/etc/strongswan/ipsec.conf是主要的配置文件,我们也主要对他进行配置

开启转发

echo 1 > /proc/sys/net/ipv4/ip_forward

关闭防火墙

service iptables stop

iptables -t nat -A POSTROUTING -s 10.31.2.0/24 -o eth0 -j MASQUERADE

四、软件的配置

1、证书的创建,我这里不再进行演示,大家可以下面的文章

   http://wangzan18.blog.51cto.com/8021085/1676529

    假设证书都已经创建好了,我们把证书放到下面的目录,如果使用PSK认证,不需要证书可以跳过这一步。

cp -r cacert.pem /etc/strongswan/ipsec.d/cacerts/
cp -r server.crt /etc/strongswan/ipsec.d/certs/
cp -r server.key /etc/strongswan/ipsec.d/private/
cp -r client.crt /etc/strongswan/ipsec.d/certs/
cp -r client.key /etc/strongswan/ipsec.d/private/
1.
2.
3.
4.
5.
2、编辑ipsec.conf

    我主要使用的是第二个链接的与共享密钥,比较简单,文章最后有介绍各参数的意义。

vim /etc/strongswan/ipsec.conf

config setup

uniqueids=never 

conn IOS_cert #使用证书认证

keyexchange=ikev1
fragmentation=yes
left=%defaultroute
leftauth=pubkey
leftsubnet=0.0.0.0/0
leftcert=server.crt
right=%any
rightauth=pubkey
rightauth2=xauth
rightsourceip=10.31.2.0/24
rightcert=client.crt
auto=add

conn android_xauth_psk #使用与共享密钥认证,不需要证书,安卓IOS都可以连接

keyexchange=ikev1
left=%defaultroute
leftauth=psk
leftsubnet=0.0.0.0/0
right=%any
rightauth=psk
rightauth2=xauth
rightsourceip=10.31.2.0/24
auto=add

conn networkmanager-strongswan

keyexchange=ikev2
left=%defaultroute
leftauth=pubkey
leftsubnet=0.0.0.0/0
leftcert=server.cert.pem
right=%any
rightauth=pubkey
rightsourceip=10.31.2.0/24
rightcert=client.crt
auto=add

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.
3、ipsec.secrets配置

这个文件默认是没有的,我自己来进行创建

vim /etc/strongswan/ipsec.secrets 

: RSA server.pem
: PSK "myPSKkey"
: XAUTH "myXAUTHPass"
[用户名] %any : EAP "[密码]"
1.
2.
3.
4.
将上面的myPSKkey单词更改为你需要的PSK认证方式的密钥;

将上面的myXAUTHPass单词更改为你需要的XAUTH认证方式的密码,该认证方式的用户名是随意的;

将上面的[用户名]改为自己想要的登录名,[密码]改为自己想要的密码([]符号去掉),可以添加多行,得到多个用户,这即是使用IKEv2的用户名+密码认证方式的登录凭据。

: PSK "PSK password" 相当于:%any %any : PSK "PSK password"
1.
    遵循:“主机 对等点 : 方法 <本机证书/协议密码> <本机证书密码>”的格式。以 :为分界,分别从左到右填充,除了各类密码缺失以 null 补位,其它都用 %any 补位(密码怎么可能是 %any)。

比如我的配置就是如下这样:

: RSA server.key
: PSK "123456a"
test %any : XAUTH "123456"
test %any : EAP "123456"
1.
2.
3.
4.
4、strongswan.conf配置

    dns可以改为你想使用的dns,可以添加两个dns1  dns2。

 vim /etc/strongswan/strongswan.conf

charon {

    load_modular = yes
    duplicheck.enable = no
    compress = yes
    plugins {
            include strongswan.d/charon/*.conf
    }
    dns1 = 114.114.114.114
    nbns1 = 114.114.114.114

}
include strongswan.d/*.conf
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

五、服务的启动

service strongswan start

然后我们就可以使用手机进行连接了,IOS手机我也试过,也是可以连接的。

    注意这里使用的是Xauth认真的IPSec *

    点击进行登录,输入我们在文件ipsec.secrets设定的账号密码。

    如下显示连接成功,可以打开浏览器查看我们的地址。

    连接上去之后,我们可以在服务器上面查看*的连接状态等等,可以使用strongswan命令查看,如下:

六、ipsec.conf配置文件的详解

   其中config setup只能出现一次,而conn <连接名称> 可以有很多个。这里的名称不是预定义的,可以随意写,只要你能识别就行,主要用来定义一种连接,就是为了让你在日志里好找。

1、新版strongswan里config setup的内容不如旧版的多,许多旧版必须有的选项都被作废了。比如:

plutostart新版所有的ike协议都由原来ikev2的daemon:charon接管。根本就没有pluto了。

nat_traversal新版所有的ike协议都是可以穿越路由器(NAT)的。

virtual_private定义服务器的局域网IP地址。现在被魔术字0.0.0.0/0取代了。

pfs完美向前保密,用于rekey时。意思是你现在的密钥互换过程如果被攻破了,会不会对已经互换过的密钥产生影响。以前一般设置成no来适用于IOS这种客户端会以积极模式发出非加密的rekey请求的情况。现在这个选项完全没作用了。第一阶段永远是完美向前保密的,第二阶段(esp)如果指定了DH组那么也是完美向前保密的,但是默认加密方法就已经指定了DH组。所以该选项永远为yes。

2、而另外旧版和新版都有的选项也都定义了默认值,比如:

strictpolicy是否一定需要证书吊销列表(CRL)的URL。默认就是no。

charonstart是否启动ikev2的daemon。这是旧版加入的,因为那个时候的主力是pluto。现在默认就是yes,你改成no那你连原先pluto的连接都无法连接,因为ike协议的实现全被charon 接管了。

    所以config setup基本上占位就行了。这里我们修改了uniqueids的值来实现多设备同时在线。

3、而conn最主要要理解左右的概念。其实左右是可以不分的,它们只是用来表示一个连接的两端。只是在如果你定义的不够全面时,左侧会默认被认为是本机(你的VPS),右侧默认为他机(你的笔记本),即以左为尊。

left/right是左右id。它们用来识别服务器/客户端,可以是证书的判别名(DN),比如 "C=CN, O=strongSwan, CN=strongSwan CA",也可以是 IP 地址,也可以是 EAP 的用户名,还可以是魔术字 %any,表示什么都行。只是在 5.0.0 之前,为本机这边定义 %any 的话,ikev1 连接即 keyexchange=ikev1 的连接是识别不了,所以要改成 %defaultroute 表示自己从 ifconfig 里取 IP。为了和 right 的 %any 区分开,我们使用这种方法。所以说到最后这两个选项似乎没有什么用。但它们是必须的。

leftauth/rightauth这是最重要的改动。新版主要是作废了之前的authby和 xauth=server/client选项而都改用这种方法。因此使得ikev1也能够出现混血认证(左右两边认证的方法不同)了。参数主要有pubkey表示用证书,psk表示用密码,eap表示用扩展验证协议。

leftauth2/rightauth2是为了应对旧版很常见的authby=xauthpsk/xauthrsasig 的。现在xauth 只能写在这里。而psk对应leftauth/rightauth里的 PSK 方法,rsasig则对应pubkey方法。

leftsubnet最重要的,引入了魔术字 0.0.0.0/0。如果你在右侧为客户端分配虚拟 IP 地址的话,那表示你之后要做iptables转发,那么左边就必须是用魔术字。

leftcert/rightcert就是指定证书名字。

rightsourceip为客户端分配的虚拟IP段。

auto定义strongswan启动时该连接的行为。start是启动; route是添加路由表,有数据通过就启动; add是添加连接类型但不启动; ignore是当它不存在。默认是ignore。看起来似乎是route比较好,但问题是我们服务器端不能预分配虚拟IP,所以服务器端一般用的都是add。而客户端文本配置可以选择start。

    另外说下旧版的 xauth=server/client 的问题。它表示在服务器端还是在客户端执行 xauth 认证。而在新版中主要通过左右方向来体现。比如你在服务器端执行认证,那认证请求是由客户端发出的,所以要写 rightauth2=xauth。如果在客户端执行认证,那认证请求是服务器发出的,所以要写 leftauth2=xauth。

    另外网上很常见的一个配置选项是 leftfirewall=yes。这是完全错误的。看上去它的唯一作用是定义你的服务器是不是在防火墙后面,但实际上它是作为 ipsec_updown 脚本的参数被开发出来,是表明你的本机 subnet 是不是用 iptables 转发/伪装出来的。如果是的话,就调用 left/rightupdown 定义的路径下的脚本,脚本的作用是对通过 ipsec 连接的数据包进行 iptables 豁免。

    之所以说它是错到离谱的(虽然没有产生影响),因为这些人完全就不懂,有公网 IP 的服务器的 subnet 很少是伪装的。另外必须写了脚本该选项才有意义,没看过一个定义了这个选项的人写过脚本。还有,leftsubnet=0.0.0.0/0 通过魔术字把 subnet 定义为了 any,你根本没法写脚本啊。所以我们这里完全就不用。

至于某类型连接,主要是根据设备规格定义的,一些特殊选项的解释如下:

fragmentation=yes 开启对 iOS 拆包的重组支持。

ike=aes256-sha1-modp1024! Windows 指定的第一阶段加密方法。

rekey=no 服务器对 Windows 发出 rekey 请求会断开连接。

rightsendcert=never 因为这是一个混血连接。服务器对自己的身份进行认证时使用的是证书,而服务器对客户端的认证使用的只是 eap-mschapv2。如果不设置的话默认是 ifasked,意思是如果服务器向客户端请求证书,客户端就会给它,但客户端给不出,连接就会断。这里设置为客户端永远不给,实际上的意思其实是服务器不要向客户端请求证书。

eap_identity=%any 使用 Windows 的 eap 身份。不然会出现”no eap key found for host “错误。

六、客户端的设置

IOS

    把CA证书和之前做好的pkcs12(.p12)发邮件给自己。在IOS上收邮件,导入两者。然后新建 IPSec *

服务器,都是IP或都是URL

账户和密码写ipsec.secrets 里XAUTH前后的那两个

如果要使用证书,证书选刚才的那个。否则可以不使用证书,输入ipsec.secrets 里设置的PSK密码。

Android

1、IPSec Xauth PSK

主要还是:

服务器,都是IP或都是URL

IPSec预共享密钥:写ipsec.secrets里PSK后面的那个密码。

然后登入时还是用XAUTH前后的那两个做用户名密码。

2、"strongSwan * Client" for Android 4.0 (ICS)+

    这是官方自己出的客户端,Google Play 里就有。

    把之前做好的 pkcs12 发邮件给自己。实际上 pkcs12 里就包含了CA证书,iOS是有bug才必须明确要求导入CA证书(鄙视之)。Android不用。直接在GMail里点击就会提示你导入。

    然后打开官方客户端,新建方案:

Gateway就是服务器,同上

Type 选 IKEv2 Certificate

User certificate 选你刚才导入的

取消自动选择CA证书,然后在用户证书里选你刚才从pk12导入的

Windows的客户端我还是建议使用pptp或者l2tp open*

七、问题调试

如果没有特殊需要,服务器端的日志就足够检测出绝大多数问题的来源。

日志阅读技巧

    strongswan 的 charon daemon 启动后,会初始化并加载之前你定义好的 conn,这部分 log 是没有必要去读的。当然在你配置有问题时可能就有必要了,但当配置有问题的时候,service strongswan start会失败,strongswan status就会指出你配置问题所在的行号(=。=)...

服务器端调试

/var/log/strongswan-charon.log 文件

需要在/etc/strongswan/strongswan.d/charon-logging.conf里面开启调试日志功能

IOS调试

    越狱安装iFile。编辑/etc/racoon/racoon.conf文件,找到 #log debug; 字段,改成:

log debug;
path logfile "/var/log/racoon.log";
1.
2.
Android 调试

strongSwan 官方客户端提供了日志查看功能。

android 自带的 * 调试方法如下:

打开「终端模拟器」,输入 su,会弹出超级用户,允许。

cd /storage/sdcard0
logcat -f ./log.txt
1.
2.
然后用 Airdroid 等工具把 SD 卡中的 log.txt 传到电脑上,打开搜索 * 即可。

八、总结

   经过我测试得出的结论,我目前只测试了IOS 8还有安卓手机小米Note,都是使用的xauth认证,没有使用证书,我的小米Note是可以连接的上,但是页面加载有问题,查看日志他是使用的android_xauth_psk这个连接,也没有找到问题的原因,同样的配置用IOS连接,因为我们使用的是IOS自带的IPSec *连接,也没有使用证书,参数和安卓的连接一样,因为没有使用证书,识别的也是android_xauth_psk这个连接,但是访问都是一切正常的。

    如果有什么问题欢迎大家和我一起探讨。

附:快速安装文档

环境准备

service iptables stop
setenforce 0
echo 1 > /proc/sys/net/ipv4/ip_forward
yum install strongswan -y
1.
2.
3.
4.

设置主配置文件

vim /etc/strongswan/ipsec.conf

config setup

uniqueids=never

conn mobile_xauth_psk

keyexchange=ikev1
left=%defaultroute
leftauth=psk
leftsubnet=0.0.0.0/0
right=%any
rightauth=psk
rightauth2=xauth
rightsourceip=10.31.2.0/24
auto=add

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

添加数据包伪装转发

iptables -t nat -A POSTROUTING -s 10.31.2.0/24 -o eth0 -j MASQUERADE
1.

添加账号密码等信息

vim /etc/strongswan/ipsec.secrets

: PSK "123456a"
test %any : XAUTH "123456"
test %any : EAP "123456
1.
2.
3.

配置strongswan文件

vim /etc/strongswan/strongswan.conf

charon {

    load_modular = yes
    plugins {
            include strongswan.d/charon/*.conf
    }
    dns1 = 8.8.8.8
    nbns1 = 8.8.4.4

}

include strongswan.d/*.conf
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.

启动*服务连接

登录后复制
service strongswan start
chkconfig strongswan on
1.
2.

按照上面要求,账号密码如下,手机连接即可。

账号:test
密码:123456

预共享密钥:123456a

©著作权归作者所有:来自51CTO博客作者wzlinux的原创作品,请联系作者获取转载授权,否则将追究法律责任
CentOS 用Strongswan搭建IPSec *
https://blog.51cto.com/wzlinux/1683915

本文原地址: http://feitianzhi.com/boke/index.php/archives/46/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


参考文章:https://www.cnblogs.com/sealin/p/13948629.html

前言:以下将会唠叨一大堆内容,建议不要读直接进入正文。现已安装了一个debian xfce的操作系统,分区表是MBR(l传统模式引导),

通过写盘工具烧录,能在烧录大多x86的板子上面运行.现有遇到一种奇葩的终端-z8350, 只支持UFFI引导, 看了bios的设置,只有寥寥

几个选项.最终判断它真的只能是UEFI引导, 不知道是bios被去掉的原因,还是这个板子或芯片原因. 由于对bios又不熟,只能从系统引导

层入手了(其实这个也不熟).那为什么不直接在8350。这款终端上面直接安装UEFI引导呢.主要两方面原因:1原本已经稍好的系统,

做了大量的系统更改,编译安装不少软件,前后升级软件依赖库的,再重新安装巨麻烦,容易漏掉哪个细节而留下bug.2 另一原因

是Debian使用UEFI安装,无法烧录到其他板子上,即使是相同型号的板子也不行。但在一些Ubuntu和fedoras的UEFI可以,发现有一

个地方不一样,fedoras的UEFI的分区表是MBR,而debian的分区表是gpt的,也许是这个原因,以前刚开始做这个debian系统时,

尝试过安装debian转换MBR分区表,要么安装失败,要么安装完又变回gpt分区表,所以就放弃这个想法了。

正文:

 1、新建一个EFI分区 (好在之前保留了一个vfat分区,可以直接拿来用,不然就只能缩容了,我的全部分挂载在/

       目录,而且还是非lvm,要对这里动刀十分麻烦。)

         (1)新建efi分区,这里使用 fdisk /dev/sdx 命令新建,然后mkfs.vfat格式化。

            还有需要将分区标记为efi分区,fdisk这个命令应该可以修改,但我没折腾,直接装gparted图像化工具改(apt install gparted)。

         (2)创建/boot/efi,目录然后将刚新建的efi分区挂载上去。

             在/etc/fstab编辑增加, (使用blkid查看分区uuid)

                UUID=xxxx-xxxx  /boot/efi vfat rw 0 0  

             # mount -a   (挂载/etc/fstab刚填写的)

        

 2、安装grub-efi

   sudo apt install grub-efi


  3、使用grub-install 生成efi引导信息 (如果不安装grub-efi会报错缺少modinfo.sh)

       # grub-install --boot-directory=/boot/efi --target=x86_64-efi --efi-directory=/boot/efi --removable

       会在/boot/efi/生成 EFI/BOOT/BOOTX64.EFI

       # grub-install --target=x86_64-efi --boot-directory=/boot/efi  --efi-directory=/boot/efi

   会在/boot/efi/生成 EFI/debian/grubx64.efi

       --boot-directory加不加也不影响最后结果,不加--boot-directory这里执行会可能报错,提示啥未注册或者环境不支持类似(记不太清),

       报错没太大关系,只要/boot/efi 目录下 生成对应的efi文件,有就可以了

4、重启进入BIOS

         进入BIOS后,找到引导项将会看到一个硬盘名字,一个是UEFI+硬盘名字, 还有一个是 写着Debian。

        (1)硬盘名字:原先的mbr传统引导

        (2)UEFI+硬盘名字:  这个是加了 --removable 用于移动设备,比如U盘

        (3)Debian:这个是没加--removable 参数,个人理解是对于非移动设备

          结果3个都可以引导进去。搞那么一个--removable,只是为了兼容性好一点,将做好这个系统,烧录到z8350也可以通过UEFI成功引导。


拓展记录:

     1,grub-pc 的-pc是指MBR分区传统引导的对应/usr/lib/grub/i386-pc

     2,grub-efi 的是指uefi引导的,安装了才会有/usr/lib/grub/i386-efi

     3,grub-pc和grub-efi这两个包冲突,只能存在一个,grub-install --target 参数依赖用到

     4,网上提到bios是否支持UEFI,查看 /sys/firmware/efi 这个目录是否存在,其实并不是很正确。

     按我实验所得出的结果是,使用传统引导就不存在/sys/firmware/efi, 而使用UEFI 引导进去

     则才会有这个目录/sys/firmware/efi ,所以并不能说明bios是否支持UEFI。

   linux使用UEFI引导可能需要把secury boot 选项关掉,由于UEFI签名的问题。

     5,由于grub-install 误操作生成一些其他的文件在/boot/efi/, 那先把这个目录所有文件清除

     6,进入grub>命令行,手动引导方法:

         (1)用 ls 查看文件 ,我的机器是列出(hd0) (hd0,msdos1) (hd0,msdos2) 

                 grub> ls (hd0,msdos2)/   查看哪个是root分区,我这里就是(hd0,msdos2)

                 grub> set root=(hd0,msdos2)

          (2) 加载/boot/grub/grub.cfg 文件,这个命令需要在set root=(hd0,msdos2)之后,不然找不到这个文件

                grub> source /boot/grub/grub.cfg   不知这条命令后面会提示no suitable video mode found

          (3) 装载内核:linux /boot/vmlinuz-xxxx root=/dev/sdx  (这里的xxxx根据你系统内核版本,按tab就可以补全, sdx 这里是根分区,根据实际情况,不能直接(hd0,msdos2)格式)

               grub> linux /boot/vmlinuz-4.9.0-9  root=/dev/sda2 

               grub> initrd /initrd.img  

         (4)启动m 看能否引导到桌面系统,反正我是成功了,如果报其他错就自行解决了。

                 grub> boot

本文原地址: http://feitianzhi.com/boke/index.php/archives/45/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


参考文章:https://blog.csdn.net/JustDoIt_201603/article/details/106629059

一、cat /proc/meminfo 各字段详解

/ $ cat /proc/meminfo
MemTotal:         877368 kB  :所有可用RAM大小(即物理内存减去一些预留位和内核的二进制代码大小)(HighTotal + LowTotal),系统从加电开始到引导完成,BIOS等要保留一些内存,内核要保留一些内存,最后剩下可供系统支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的。
MemFree:           22516 kB  :LowFree与HighFree的总和,被系统留着未使用的内存,MemFree是说的系统层面
MemAvailable:     470244 kB  :应用程序可用内存数。系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以MemFree不能代表全部可用的内存,这部分可回收的内存加上MemFree才是系统可用的内存,即:MemAvailable≈MemFree+Buffers+Cached,它是内核使用特定的算法计算出来的,是一个估计,MemAvailable是说的应用程序层面
Buffers:            1772 kB  :用来给文件做缓冲大小
Cached:           459224 kB  :被高速缓冲存储器(cache memory)用的内存的大小(等于 diskcache minus SwapCache )
SwapCached:           16 kB  :被高速缓冲存储器(cache memory)用的交换空间的大小,已经被交换出来的内存,但仍然被存放在swapfile中。用来在需要的时候很快的被替换而不需要再次打开I/O端口
Active:           333148 kB  :在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非非常必要否则不会被移作他用. (Active(anon) + Active(file))
Inactive:         330384 kB  :在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径. (Inactive(anon) + Inactive(file))
Active(anon):     104368 kB  :活跃的与文件无关的内存(比如进程的堆栈,用malloc申请的内存)(anonymous pages),anonymous pages在发生换页时,是对交换区进行读/写操作
Inactive(anon):   104508 kB  :非活跃的与文件无关的内存(比如进程的堆栈,用malloc申请的内存)
Active(file):     228780 kB  :活跃的与文件关联的内存(比如程序文件、数据文件所对应的内存页)(file-backed pages) File-backed pages在发生换页(page-in或page-out)时,是从它对应的文件读入或写出
Inactive(file):   225876 kB  :非活跃的与文件关联的内存(比如程序文件、数据文件所对应的内存页)
Unevictable:        6708 kB  :
Mlocked:            1428 kB  :
HighTotal:        261888 kB  :高位内存总大小(Highmem是指所有内存高于860MB的物理内存,Highmem区域供用户程序使用,或用于页面缓存。该区域不是直接映射到内核空间。内核必须使用不同的手法使用该段内存)
HighFree:           5680 kB  :未被使用的高位内存大小
LowTotal:         615480 kB  :低位内存总大小,低位可以达到高位内存一样的作用,而且它还能够被内核用来记录一些自己的数据结构
LowFree:           16836 kB  :未被使用的低位大小
SwapTotal:        614396 kB  :交换空间的总大小
SwapFree:         611044 kB  :未被使用交换空间的大小
Dirty:                40 kB  :等待被写回到磁盘的内存大小
Writeback:             0 kB  :正在被写回到磁盘的内存大小
AnonPages:        209224 kB  :未映射页的内存大小
Mapped:           280668 kB  :设备和文件等映射的大小
Shmem:              1084 kB  :
Slab:              59840 kB  :内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
SReclaimable:      34196 kB  :可收回Slab的大小
SUnreclaim:        25644 kB  :不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack:        7504 kB  :常驻内存,每一个用户线程都会分配一个kernel stack(内核栈)
PageTables:        15508 kB  :管理内存分页页面的索引表的大小
NFS_Unstable:          0 kB  :不稳定页表的大小
Bounce:                0 kB  :
WritebackTmp:          0 kB  :
CommitLimit:     1053080 kB  :根据超额分配比率('vm.overcommit_ratio'),这是当前在系统上分配可用的内存总量,这个限制只是在模式2('vm.overcommit_memory')时启用。CommitLimit用以下公式计算:CommitLimit =('vm.overcommit_ratio'*物理内存)+交换例如,在具有1G物理RAM和7G swap的系统上,当`vm.overcommit_ratio` = 30时 CommitLimit =7.3G
Committed_AS:   16368536 kB  :目前在系统上分配的内存量。是所有进程申请的内存的总和,即时所有申请的内存没有被完全使用,例如一个进程申请了1G内存,仅仅使用了300M,但是这1G内存的申请已经被 "committed"给了VM虚拟机,进程可以在任何时间使用。如果限制在模式2('vm.overcommit_memory')时启用,分配超出CommitLimit内存将不被允许
VmallocTotal:     245760 kB  :可以vmalloc虚拟内存大小
VmallocUsed:           0 kB  :vmalloc已使用的虚拟内存大小
VmallocChunk:          0 kB  :最大的连续未被使用的vmalloc区域

1、Inactive(anon) 和 Inactive(file),分别表示anonymous pages和mapped pages。

用户进程的内存页分为两种:与文件关联的内存(比如程序文件、数据文件所对应的内存页)和与文件无关的内存(比如进程的堆栈,用malloc申请的内存),前者称为file pages或mapped pages,后者称为anonymous pages;其中LRU lists包括如下几种,在/proc/meminfo中都有对应的统计值:

  LRU_INACTIVE_ANON  –  对应 Inactive(anon)
  LRU_ACTIVE_ANON  –  对应 Active(anon)
  LRU_INACTIVE_FILE  –  对应 Inactive(file)
  LRU_ACTIVE_FILE  –  对应 Active(file)
  LRU_UNEVICTABLE  –  对应 Unevictable

Inactive list里的是长时间未被访问过的内存页,Active list里的是最近被访问过的内存页,LRU算法利用Inactive list和Active list可以判断哪些内存页可以被优先回收。

2、MemAvailable

应用程序可用内存数。系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以MemFree不能代表全部可用的内存,这部分可回收的内存加上MemFree才是系统可用的内存,即:MemAvailable≈MemFree+Buffers+Cached,它是内核使用特定的算法计算出来的,是一个估计值。

3、VmallocUsed

通过vmalloc分配的内存都统计在/proc/meminfo的 VmallocUsed 值中,但是要注意这个值不止包括了分配的物理内存,还统计了VM_IOREMAP、VM_MAP等操作的值,譬如VM_IOREMAP是把IO地址映射到内核空间、并未消耗物理内存,所以我们要把它们排除在外。从物理内存分配的角度,我们只关心VM_ALLOC操作,这可以从/proc/vmallocinfo中的vmalloc记录看到。

4、KernelStack:

Kernel stack(内核栈)是常驻内存的,既不包括在LRU lists里,也不包括在进程的RSS/PSS内存里,所以我们认为它是kernel消耗的内存。统计值是/proc/meminfo的KernelStack。64bit 系统的 task_struct size 是16KB,  32bit的系统task_struct size为 8KB,每一个用户线程都会分配一个kernel stack(内核栈),内核栈虽然属于线程,但用户态的代码不能访问,只有通过系统调用(syscall)、自陷(trap)或异常(exception)进入内核态的时候才会用到,也就是说内核栈是给kernel code使用的。
 

内存黑洞:

进程通过将memoryinfo中的内存大小相加起来,发现总是比真实内存小,那是因为有内存黑洞的存在,我们知道,Kernel的动态内存分配通过以下几种接口:

alloc_pages/__get_free_page: 以页为单位分配

vmalloc: 以字节为单位分配虚拟地址连续的内存块

slab allocator

vmalloc和slab分配的内存都会被记录在meminfo中,但通过alloc_pages/__get_free_page分配的内存,没有在/proc/meminfo中统计,不知道有多少,就像个黑洞。

参考博客《android cat /proc/meminfo 字段分析》

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/25/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


editbin

这是 Visual Studio 2017 采用的做法。我们需要使用到两个工具——editbin 和 dumpbin。前者用于编辑我们编译生成好的程序使之头信息中声明支持大于 2GB 内存,后者用于查看程序的头信息验证我们是否改好了。

编辑一个程序使之声明支持大于 2GB 内存的命令是:

editbin /largeaddressaware xxx.exe

其中,xxx.exe 是我们准备修改的程序,可以使用相对路径或绝对路径(如果路径中出现空格记得带引号)。

验证这个程序是否改好了的命令是:

dumpbin /headers xxx.exe | more

同样,xxx.exe 是我们刚刚改好准备检查的程序,可以使用相对路径或绝对路径。

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/24/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


      目前恩山上本人使用较多的固件为Padavan,PandoraBox,Bootloader部分则使用H大的Breed,这些固件使用起来体验极好,接下来浅谈一下个人对这些固件的看法,若有不当之处,还请指出

Breed部分的介绍将在下文刷机过程中展示

      PandoraBox是基于OpenWrt进行了大量国内路由适配的系统,其界面接近原生系统,并针对国情内置了不少实用的组件,通过opkg管理组件,全面汉化,翻译水平比原生系统高出不少,软件源在国内,所以下载速度较快,时区和信道都按照国内的标准预先修改了,所以对于大部分人来说,直接刷PandoraBox即可,不必费力刷原生OpenWrt,而且据说PandoraBox采用的无线驱动优于原生,对此没有太确定的消息,仅作参考

      Padavan俗称老毛子,其界面友好度极高,非常适合新手入门,不过默认主题略丑,好在可以更换,而且看起来不错,同样针对国情加入了大量组件,对332支持极好,不过扩展性较OpenWrt略有不足,但对于新手来说足矣

      我使用Padavan和PandoraBox近一年,但折腾的心是不会停止的,所以现在准备给R3G刷入原生OpenWrt,但根据OpenWrt官网上的资料和H大的某些回复来看,Breed刷OpenWrt略有困难,其原因在于给OpenWrt提交R3G支持的人,提交的flashlayout跟原厂的不兼容,而且使用了UBI,因此breed无法兼容,故breed不支持直接刷入mir3g的openwrt固件,且无法识别tar包
详情可见下方链接
https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=267455&page=1

      但此楼里有另一位大神提出了一种新的思路,见第三页aatest123的回复,其思路在于通过Breed先刷入initramfs-kernel.bin,这个文件集内核kernel和文件系统rootfs为一体,在引导期间将文件系统放在内存中,但由于内存断电后无法保存数据,所以该系统的所有设置无法保存,仅适用于不驱动flash的情况下使用,我们先通过Breed刷入该临时OpenWrt系统,重启路由器即可进入该临时系统,通过luci界面,选择系统更新,上传安装openwrt-18.06.4-ramips-mt7621-mir3g-squashfs-sysupgrade.tar(此为写此文时最新版本,可更换)
附件在此:https://pan.baidu.com/s/1SkF7WOt5GkIw6f68JP7viA 提取码: npp5

      随后路由器会自动重启,但登录后会发现进入的仍然是临时OpenWrt,这是因为Breed在刷入临时OpenWrt时刷入的是路由器的kernel0,而我们通过临时OpenWrt安装正式系统刷入的是kernel1,接下来我们将路由器断电,进入Breed(具体进入方法见Breed安装),启用环境变量,添加环境变量xiaomi.r3g.bootfw,其值为2,其目的在于使Breed启动后从kernel1启动,接下来重启,即可进入正式版OpenWrt系统,折腾第一步结束

      接下来是我当时安装时各种参考的资料分析,以及遇到的一些坑,毕竟我只能算是一位爱好者,没有接受过计算机技术教学,对于编译等东西一窍不通

      首先说说OpenWrt官网上对于R3G安装的操作,官网上的操作是针对原厂Bootloader和原厂固件的,故对于安装了Breed的我们来说,照抄是万万不行的,官网上提供两个文件,分别是mir3g-squashfs-kernel1.bin和mir3g-squashfs-rootfs0.bin,官网上的命令为:

mtd write mir3g-squashfs-kernel1.binkernel1
mtd write mir3g-squashfs-rootfs0.binrootfs0
nvram set flag_try_sys1_failed=1
nvram commit
reboot

      上述命令中nvram是uboot专有命令,Breed与uboot相互独立,参数不共用,根据国外论坛对于小米路由器原厂uboot的分析,小米路由器的kernel0包含的usb恢复的功能,就是将官方固件命名为miwifi.bin放入U盘内,断电时插入路由器,用硬物抵住reset键后插电,保持10秒左右,待黄灯快速闪动后可松手,可恢复至官方固件,这个功能可用于原厂固件损坏后的修复,也算是不错的功能,所以OpenWrt官网上的建议是将内核文件刷入kernel1

      接下来说说Breed的参数,根据H大的回复,breed的启动流程如下:
      如果kernel0存在kernel1不存在,那么启动kernel0
      如果kernel1存在kernel0不存在,那么启动kernel1
      如果kernel0和kernel1都存在,那么检查环境变量 xiaomi.r3g.bootfw的值,如果存在且值为2,那么启动kernel1,否则启动kernel0

      关于操作前的备份指令
      cat /proc/mtd:读取路由器内部分区
      插入U盘(FAT/FAT32)
      输入【df -h】查看查看U盘的分区路径
      或者输入"cd /"回车,再输入"ls -a"查看到extdisks文件,再"cd extdisks"进入到extdisks文件里用"ls -a"就能查看到你的U盘路径,我的是sda4,以下以我自己U盘的路径为例:
      备份(请自行修改回你自己的U盘路径):

dd if=/dev/mtd0 of=/extdisks/sda4/ALL.bin
dd if=/dev/mtd1of=/extdisks/sda4/Bootloader.bin
dd if=/dev/mtd2of=/extdisks/sda4/Config.bin
dd if=/dev/mtd3 of=/extdisks/sda4/Bdata.bin
dd if=/dev/mtd4of=/extdisks/sda4/Factory.bin
dd if=/dev/mtd5 of=/extdisks/sda4/crash.bin
dd if=/dev/mtd6 of=/extdisks/sda4/crash_syslog.bin
dd if=/dev/mtd7of=/extdisks/sda4/reserved0.bin
dd if=/dev/mtd8of=/extdisks/sda4/kernel0.bin
dd if=/dev/mtd9of=/extdisks/sda4/kernel1.bin
dd if=/dev/mtd10of=/extdisks/sda4/rootfs0.bin
dd if=/dev/mtd11of=/extdisks/sda4/rootfs1.bin
dd if=/dev/mtd12of=/extdisks/sda4/overlay.bin
dd if=/dev/mtd13of=/extdisks/sda4/ubi_rootfs.bin
dd if=/dev/mtd14 of=/extdisks/sda4/data.bin

      备份到最后一个mtd14可以会出现如下出错提示:
dd: can't open '/dev/mtd14': Device or resourcebusy
      该分区备份不成功无所谓,关键的mtd0-mtd4备份下来就行了。
      如果还在官版的固件下想恢复的,可使用如下命令:
      恢复(这里我们不需要该步骤,只是给有需要的人看的官版固件下的恢复步骤)

mtd write /extdisks/sda4/Bootloader.binBootloader
mtd write /extdisks/sda4/Config.bin Config
mtd write /extdisks/sda4/Bdata.bin Bdata
mtd write /extdisks/sda4/Factory.binFactory
mtd write /extdisks/sda4/crash.bin crash
mtd write /extdisks/sda4/crash_syslog.bincrash_syslog
mtd write /extdisks/sda4/reserved0.binreserved0
mtd write /extdisks/sda4/kernel0.binkernel0
mtd write /extdisks/sda4/kernel1.bin kernel1
mtd write /extdisks/sda4/rootfs0.binrootfs0
mtd write /extdisks/sda4/rootfs1.binrootfs1
mtd write /extdisks/sda4/overlay.binoverlay
mtd write /extdisks/sda4/ubi_rootfs.binubi_rootfs
mtd write /extdisks/sda4/data.bin data

Breed

      https://www.right.com.cn/forum/thread-161906-1-1.html
      这是一个非常易用的Bootloader,针对刷机主流型号进行了适配,内置DHCP服务,拥有Web图形化界面,小白也能轻松刷机,并且支持Telnet,wget等功能,可以通过TTL进行操作,具体介绍可见上述网址,选择仅看楼主,里面包含绝大多数关于Breed的资料,就不在此赘述

      如何在R3G内刷入Breed

      首先小米路由器需要开启ssh,此类教程在网上极多,是基本功,在此不多说了
      首先需要下载支持小米路由器3G的Breed,可从H大搭建的服务器https://breed.hackpascal.net/ 内下载,其型号是breed-mt7621-xiaomi-r3g.bin
      接下来通过WinSCP将文件上传至路由器内部,注意将文件协议选择为SCP,我通常将文件上传至/tmp目录下,建议将文件改名为Breed.bin,便于后续操作
      输入mtd write /tmp/breed.bin Bootloader,将Breed刷入Bootloader
若输入mtd -r write /tmp/breed.bin Bootloader,-r意味着刷入后直接重启,一旦刷错难以补救,所以建议不要加入-r,待完      全确认后再手动断开电源
      在接入电源线之前用硬物顶住路由的reset键再接电,等到路由器的指示灯狂闪的时候,松开reset键,电脑上在浏览器中输入192.168.1.1,即可进入Breed控制台

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/23/
转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


使用 GRUB2 安装 Ubuntu 18.04

      使用 GRUB2 安装 Ubuntu 18.04 的原因是机器上已经有 Ubuntu 16.04 在了,GRUB 引导自然也是有的。我以往常使用传统硬盘安装的方式, GRUB2 本身是硬盘安装的一种方式,只是引导器选择了GRUB2。好处是只要有 ISO 的安装镜像就可以了,不需要像传统的方法从源里新下载适用于硬盘的引导 vmlinux & initrd, 它们俩一般在 hd-media 目录,如下是阿里云 Ubuntu 18.04 的路径。

      https://mirrors.aliyun.com/ubuntu/dists/bionic/main/installer-amd64/current/images/hd-media/

流程

  • 下载 Ubuntu 18.04 镜像,更名为 Ubuntu-18.04.iso, 放在某盘根目录。
  • 进入 GRUB2, 在界面按提示 C 进入 Command Mode
  • ls (hdxx, msdosxx)/, 寻找 Ubuntu-18.04.iso 的存放路径。本次为 (hd2, msdos1)
  • 执行指令

    loopback loop (hd2, msdos1)/Ubuntu-18.04.iso
    linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=/Ubuntu-18.04.iso
    initrd (loop)/casper/initrd.lz
    boot

说明:

(loop)后的路径,依据 vmlinuz & initrd.lz 实际的来。可以 tab 自动补全,或 ls 查看。
linux 指令后,没有增加其它指令(quiet splash)。好处是在运行过程中,有 LOG 。解决了我因为打印机连接而 Pending 的问题。

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/21/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


参考文章:https://www.oschina.net/question/234345_52687

用例子说话

二进制

对应源码

有一个程序

a.out

main.c

需要加载插件A

libA.so

liba.c

A需要另一个动态库

libB.so

libB1.c 或 libB2.c

本文的关注点就是:到底是哪一个libB.so被加载

目录结构:

/home/debao/ttt/a.out
/home/debao/ttt/libA.so
/home/debao/ttt/libB.so
/usr/lib/libB.so
具体源码
main.c ==> ./a.out

include <stdio.h>

include <dlfcn.h>

typedef int (*funcA)(int, int);
int main()
{

void * plugin = dlopen("./libA.so", RTLD_LAZY);
funcA f = (funcA)dlsym(plugin, "funcA");
printf("main: %d\n", f(3,4));
return 0;

}
liba.c ==> ./libA.so

include <stdio.h>

int funcB(int, int);
int funcA(int a, int b)
{

printf("hello from funcA\n");
return funcB(a, b);

}
libb1.c ==> ./libB.so

include <stdio.h>

int funcB(int a, int b)
{

printf("Hello from funcB 1\n");
return a*b;

}
libb2.c ==> /usr/lib/libB.so

include <stdio.h>

int funcB(int a, int b)
{

printf("Hello from funcB 2\n");
return a*b;

}
编译库文件
编译动态库libB.so

$ gcc -shared -fPIC libb2.c -o libB2.so
$ sudo mv libB2.so /usr/lib/libB.so
$ gcc -shared -fPIC libb.c -o libB.so
编译动态库libA.so

$ gcc -shared -fPIC liba.c -o libA.so -L. -lB
顺便看看该elf文件的头部信息:

$ readelf libA.so -d

Dynamic section at offset 0xf20 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libB.so]
0x00000001 (NEEDED) Shared library: [libc.so.6]
...
恩,只有库的文件名信息,而没有路径信息。

编译程序
第一次编译运行(什么路径都不加)

$ gcc main.c -ldl
$ ./a.out
hello from funcA
Hello from funcB 2
main: 12
程序:dlopen从当前目录找到libA.so,然后却在/usr/lib/中找到libB.so(没有使用当前目录的libB.so,这是我们需要的么?)

第二次编译运行(使用DT_RPATH)

$ gcc main.c -ldl -Wl,--rpath=.
$ ./a.out
hello from funcA
Hello from funcB 1
main: 12
恩,使用当前目录的libB.so,很理想的东西

可是,由于DT_RPATH无法被环境变量LD_LIBRARY_PATH覆盖,不是不建议被使用,而是建议使用DT_RUNPATH么?

第三次编译运行(使用DT_RUNPATH)

$ gcc main.c -ldl -Wl,--rpath=.,--enable-new-dtags
$ ./a.out
hello from funcA
Hello from funcB 2
main: 12
问题重新出现,使用的系统路径中的libB.so 而不是当前目录下的。

程序头部信息
通过下列命令可以查看:

$ readelf -d a.out
为了完整起见,列出前面3次编译的程序的信息:

没有rpath和runpath

Dynamic section at offset 0xf20 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048360
...
包含rpath

Dynamic section at offset 0xf18 contains 22 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [.]
0x0000000c (INIT) 0x8048360
....
包含rpath和runpath

Dynamic section at offset 0xf10 contains 23 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [.]
0x0000001d (RUNPATH) Library runpath: [.]
原因
RPATH and RUNPATH给出这个问题的答案:

Unless loading object has RUNPATH:

RPATH of the loading object,
    then the RPATH of its loader (unless it has a RUNPATH), ...,
    until the end of the chain, which is either the executable
    or an object loaded by dlopen
Unless executable has RUNPATH:
    RPATH of the executable

LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs
用它解释第一个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序没有RUNPATH,故而
使用其RPATH (没有)
环境变量LD_LIBRARY_PATH,(没有)
libA.so 的RUNPATH (没有)
ld.so.cache (没有命中)
默认路径/usr/lib (命中)
用它解释第二个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序没有RUNPATH,故而
使用其RPATH (命中)
用它解释第三个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序有RUNPATH,(继续前行)
环境变量LD_LIBRARY_PATH,(没有)
libA.so 的RUNPATH (没有)
ld.so.cache (没有命中)
默认路径/usr/lib (命中)
有意思的就是这个程序了,可执行程序的RUNPATH是一个重要的判断条件,却并不被做为这儿搜索路径!!

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/19/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


本文纯探讨技术实现,请大家抱着学习交流之目的进行阅览。

测试环境:
服务器端:CentOS 7.0、openvpn-2.3.10
客户端 :Fedora 23

服务器端安装与配置:
安装obfsproxy
1、[root@1st ~]# yum install gcc python-pip python-devel
2、[root@1st ~]# pip install obfsproxy
3、[root@1st ~]# obfsproxy
usage: obfsproxy [-h] [-v] [–log-file LOG_FILE]
[–log-min-severity {error,warning,info,debug}] [–no-log]
[–no-safe-logging] [–data-dir DATA_DIR] [–proxy PROXY]
{managed,obfs2,dummy,obfs3,scramblesuit,b64} …
以上三步,我们就完成了obfsproxy的安装工作,接下来我们开始配置。obfsproxy一般使用obfs3或者scramblesuit模式,scramblesuit是obfs3的加强版,使用密码加密。这样就无法模拟obfs客户端来探测被混淆的是什么。下面以scramblesuit作为示范。
注意:scramblesuit的密码必须为BASE32字符。
BASE32字符是由:ABCDEFGHIJKLMNOPQRSTUVWXYZ234567组成,且必须为32位。

[root@1st ~]# obfsproxy –data-dir ~/.obfs/ scramblesuit –dest 127.0.0.1:1194 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 server 0.0.0.0:1234 &

由于我们是通过obfsproxy来实现服务器端与客户端之间的加密通信,所以openvpn不用监听在服务器端的IP地址上,可以监听在127.0.0.1这样的本地地址。上面的命令中:127.0.0.1:1194就是需要被混淆的端口(协议),0.0.0.0:1234是混淆后对外监听的端口。如果不需要后台运行则去掉最后的 & 。

运行成功后应该会提示:

2015-08-21 22:54:12,282 [WARNING] Obfsproxy (version: 0.2.13) starting up.
2015-08-21 22:54:12,282 [ERROR]

Do NOT rely on ScrambleSuit for strong security!

至此服务端已经配置完成。

客户端安装与配置
关于在Windows和Fedora 23下的openvpn客户端配置,不再本文的讨论范围之内。
Windows客户端
首先:需要在python官方网站上下载你windows对应python版本,本文中下载的是python-2.7.11.amd64,因为测试系统是windows 7 64位。
其次:需要在http://www.voidspace.org.uk/python/modules.shtml这个网站下载pycrypto-2.6.win-amd64-py2.7,如果没有这个文件,将会在安装obfsproxy是报错。
第三:在正确安装上述两个软件后,需要从新启动一下你的操作系统。
第四:在命令行状态下执行:C:\>pip install obfsproxy,如果一切顺利,就可以执行下面的命令了:
c:>obfsproxy scramblesuit –dest xxx.xxx.xxx.xxx(此处是openvpn所在服务器的IP地址):1234 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 client 127.0.0.1:56789 &

fedora 23客户端
首先,用dnf命令检查python-crypto.x86_64、gcc.x86_64、redhat-rpm-config软件包是否安装,如果没有安装,请参照下面的命令进行安装。
[root@f23 ~]# dnf install python-crypto.x86_64
[root@f23 ~]# dnf install gcc.x86_64
[root@f23 ~]# dnf install redhat-rpm-config
[root@f23 ~]# sudo dnf install redhat-rpm-config
此命令解决:gcc: error: /usr/lib/rpm/redhat/redhat-hardened-cc1: No such file or directory的报错

[root@f23 ~]# pip install obfsproxy
[root@f23 ~]# obfsproxy scramblesuit –dest xxx.xxx.xxx.xxx(此处是openvpn所在服务器的IP地址):1234 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 client 127.0.0.1:56789(此处的端口号何以随意指定,不超出范围就好)

在本地客户端,我们通过obfsproxy将所有流量发给服务器端obfsproxy监听的端口,再由obfsproxy重定向到 OpenVPN,这样OpenVPN客户端就不知道服务器IP是多少,没办法对到 OpenVPN 服务器的流量进行特殊处理,所以我们需要手动将到服务器的路由固定下来,假设你的服务器端IP为xxx.xxx.xxx.xxx,本地客户端的网关地址是192.168.1.1,我们以fedora 23为例,添加路由的命令:
[root@f23 ~]# route add -host xxx.xxx.xxx.xxx gw 192.168.1.1(这一点非常重要)

OK,万事具备,祝大家有一个愉快的开始!