月度归档:2018年01月

CentOS 7 编译安装nginx并启用TLS1.3

更新日志

20180207 修正部分错误。
如果TLSv1.3如期发布,OpenSSL 1.1.1 将于2018年4月17日面向公众发布。截至2018年1月27日,OpenSSL开发至TLSv1.3 draft 23,暂时不推荐用于生产环境。对于服务器来说,我还是喜欢CentOS,支持周期很长,折腾一次可以用很长世间,因此以下记录一下在基于LNMP的CentOS 7 系统上启用TLSv1.3的过程。

1 升级系统

yum update

升级后的系统版本为:

cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core)

2 安装官方mainline版的nginx

通过官方源安装nginx的目的是:
自动生成nginx的配置文件,减少大量的工作;
获取nginx的编译参数。

配置源:

vi /etc/yum.repos.d/nginx.repo

写入如下内容:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1

安装nginx:

yum install nginx -y

查看nginx版本:

nginx -v
nginx version: nginx/1.13.8

获取编译参数:

nginx -V
nginx version: nginx/1.13.8
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

修改nginx源,将enabled=1改为enabled=0,防止yum update时nginx被更新掉

vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=0

3 编译nginx

安装可能用到的依赖:

yum install -y git gcc gcc-c clang automake make autoconf libtool zlib-devel libatomic_ops-devel pcre-devel openssl-devel libxml2-devel libxslt-devel gd-devel GeoIP-devel gperftools-devel  perl-devel perl-ExtUtils-Embed

获取源码:

git clone https://github.com/nginx/nginx.git
git clone https://github.com/openssl/openssl.git
git clone https://github.com/grahamedgecombe/nginx-ct.git

nginx-ct是启用证书透明度(Certificate Transparency)策略的模块。为了启用Certificate Transparency和TLSv1.3,需要额外加入如下编译参数:

--add-module=../nginx-ct/ --with-openssl=../openssl/ --with-openssl-opt=enable-tls1_3

加在官方编译参数后面,简单修改形成完整的编译参数:

auto/configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-module=../nginx-ct/ --with-openssl=../openssl/ --with-openssl-opt=enable-tls1_3

进入nginx源码目录,并输入如上完整的编译参数。如果直接编译(make),会遇到“pthread_atfork”相关错误:

-Wl,-z,relro -Wl,-z,now -pie -ldl -lpthread -lpthread -lcrypt -lpcre ../openssl//.openssl/lib/libssl.a ../openssl//.openssl/lib/libcrypto.a -ldl -lz \
-Wl,-E
../openssl//.openssl/lib/libcrypto.a(threads_pthread.o): In function `fork_once_func':
threads_pthread.c:(.text+0x16): undefined reference to `pthread_atfork'
collect2: error: ld returned 1 exit status
make[1]: *** [objs/nginx] Error 1

因此config之后,先不要编译,而是先修改nginx目录下objs内的Makefile:

vi ./objs/Makefile

找到这行:

-Wl,-z,relro -Wl,-z,now -pie -ldl -lpthread -lpthread -lcrypt -lpcre ../openssl//.openssl/lib/libssl.a ../openssl//.openssl/lib/libcrypto.a -ldl -lz \

将第一个“-lpthread”删除,将第二个“-lpthread”移至行末“\”之前,看起来是这样:

-Wl,-z,relro -Wl,-z,now -pie -ldl -lcrypt -lpcre ../openssl//.openssl/lib/libssl.a ../openssl//.openssl/lib/libcrypto.a -ldl -lz -lpthread \

然后顺利编译:

make

查看编译好的nginx信息:

./objs/nginx -v
nginx version: nginx/1.13.9

备份已经安装好的官方mainline版,安装编译版:

mv /usr/sbin/nginx /usr/sbin/nginx.1.13.8.20180127.official.mainline
cp ./objs/nginx /usr/sbin/

4 修改nginx配置文件内的ssl_protocolsssl_ciphers,启用TLSv1.3

...
ssl_protocols          TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers            TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:ECDHE+aECDSA+CHACHA20:ECDHE+aRSA+CHACHA20:ECDHE+aECDSA+AESGCM:ECDHE+aRSA+AESGCM:ECDHE+aECDSA+AES256+SHA384:ECDHE+aRSA+AES256+SHA384:ECDHE+aECDSA+AES256+SHA:ECDHE+aRSA+AES256+SHA;
...

重启nginx服务以使修改生效:

systemctl restart nginx

5 测试TLSv1.3是否生效

5.1 使用testssl工具
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh --help

命令为(coldawn.com需要换成自己的域名):

./testssl.sh -p coldawn.com
...
 Testing protocols via sockets except SPDY+HTTP2

 SSLv2      not offered (OK)
 SSLv3      not offered (OK)
 TLS 1      offered
 TLS 1.1    offered
 TLS 1.2    offered (OK)
 TLS 1.3    offered (OK): draft 23
 SPDY/NPN   http/1.1 (advertised)
 HTTP2/ALPN http/1.1 (offered)
...

详细的情况,用大写的P作为参数:

./testssl.sh -P coldawn.com

 Testing server preferences

 Has server cipher order?     yes (OK)
 Negotiated protocol          TLSv1.3
 Negotiated cipher            TLS13-AES-256-GCM-SHA384, 253 bit ECDH (X25519)
 Cipher order
    TLSv1:     ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA
    TLSv1.1:   ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA
    TLSv1.2:   ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-SHA384
               ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA
    TLSv1.3:   TLS13-AES-256-GCM-SHA384 TLS13-CHACHA20-POLY1305-SHA256 TLS13-AES-128-GCM-SHA256 TLS13-AES-128-CCM-8-SHA256 TLS13-AES-128-CCM-SHA256
5.2 使用现代浏览器

Chrome正式版 64.0.3282.119(2018年1月27日)仅支持半年前就不再更新的draft 18,不支持TLS 1.3 draft 23。推荐使用Canary 金丝雀版66.0.3332.0(2018年1月27日):

http://www.google.com/chrome/browser/canary.html?platform=win64

安装后,地址栏输入:

chrome://flags/#tls13-variant

下拉右侧列表,选中“Enableed(Draft 23)”,重启浏览器,查看https://tls13.crypto.mozilla.org/看是否能正常访问来确定浏览器自身是否支持Draft 23。
然后访问域名,查看证书相关信息:

 Connection - secure (strong TLS 1.3)
The connection to this site is encrypted and authenticated using TLS 1.3 (a strong protocol), X25519 (a strong key exchange), and AES_256_GCM (a strong cipher).

HTML网页中插入经base64编码的中文(Data URLs)的一个方法

Data URLs出现的目的是将经base64编码的小文件直接插入文档中。相对常用的用法是将小图片转换为Data URLs直接嵌入到网页中。
有时候我们在编写网页时写入中文会出现乱码,这时我们想到了Data URLs。比如说,有人问:把base64编码格式的中文显示在HTML中,该怎么做,回答者认为是不可以的。
其实,方法也不是没有。举个例子,我们想在网页中以Data URLs方式写入“中文字符”四个字,其过程是:
1 将“中文字符”四个字利用在线编码工具进行base64编码,编码后为

5Lit5paH5a2X56ym

2 按照示例,添加“前缀”、“类型”后,Data URLs为:

data:text/plain;base64,5Lit5paH5a2X56ym

3 将上述URL复制到Chrome的地址栏进行解码,发现为乱码:

涓枃瀛楃

4 原因是对于text文本,Data URLs默认的编码类型是US-ASCII。所以对于中文文本来说,需要将编码类型注明为UTF-8,Data URLs的正确写法是:

data:text/plain;charset=UTF-8;base64,5Lit5paH5a2X56ym

此时再复制到Chrome地址栏,则会正常显示其内容:

中文字符

5 直接将上述Data URLs数据插入HTML网页中,不会解析为“中文字符”,而是直接显示这串数据。这时需要使用到一个HTML5引入的标签:embed,其包含一个类型type的属性。写法为:

<embed src="data:text/plain;charset=UTF-8;base64,5Lit5paH5a2X56ym" type="text/plain" />

将上述Data URLs数据插入HTML网页中则会正确解析为“中文字符”。

上述方法可以把base64编码格式的中文显示在HTML中,但是其显示样式还需要进一步调整。

在 Mac 或 PC 上更改Apple ID 国家或地区为美国的方法

将iCloud数据放到中国有国家安全和苹果方面的考虑,云上贵州也会为当地带来经济增长。大家都注意到了隐私声明:《iCloud(由云上贵州运营)条款与条件》中有意思的地方之一:

您理解并同意,苹果公司和云上贵州有权访问您在此服务中存储的所有数据,包括根据适用法律向对方和在彼此之间共享、交换和披露所有用户数据(包括内容)的权利。

虽然明知早已没有隐私,但是仍有人以为更改国家和地区就可以避免将iCloud数据存放在云上贵州从而避免所有数据被有权访问。有些人尝试了但没有成功,卡在付款方式那里,没有“无”这个选项。

付款信息为何没有“无”

苹果官方给出了“如果您无法在编辑 Apple ID 付款信息时选取“无””的解释和解决方案,简要的记录如下:
1 如果您有未付余款或应付账款
您必须先付清余款,然后才能选择“无”作为付款方式。
2 如果您有自动续订的订阅
除非您取消订阅,否则可能无法选择“无”。
3 如果您是首次使用 iTunes Store 或 App Store
如果您是首次通过现有的 Apple ID 来使用商店,则必须提供付款方式。创建帐户后,您可以将付款信息更改为“无”。
4 如果您不在创建的 Apple ID 所属的国家或地区
如果您是首次创建 Apple ID,而且创建时身处这个 Apple ID 所属的国家或地区之外的地方,那么您必须输入付款方式。这种情况下,您无法选择礼品卡或商店余额作为付款方式。
例如,如果您身处美国,但所创建的 Apple ID 的账单邮寄地址却在中国,那么您将无法选取“无”作为付款方式。
5 如果您更改了帐号所属国家或地区
当您更改现有 Apple ID 所属的国家或地区时,必须提供付款方式并更新您的账单选项。这种情况下,您无法选择礼品卡或商店余额作为付款方式。更改国家或地区后,如果您要移除付款方式,可将付款信息更改为“无”。
6 如果您是“家人共享”的一员
当您设置“家人共享”时,家庭组织者必须提供有效的付款方式。这个付款方式将用于家庭成员发起的所有购买,且只有家庭组织者可以更改。
如果您要停止使用“家人共享”,可以解散您的家庭群组。

可行的做法

参照上面的条目逐一排查,该付清的付清,该取消的取消,该解散的解散,然后全程使用美国IP,按照官方提供的方法:在 Mac 或 PC 上更改您的国家或地区,使用iTunes进行操作。
1 打开iTunes,登陆Apple ID。
2 从您电脑屏幕顶部或 iTunes 窗口顶部的菜单栏中,选取“帐户”>“查看我的帐户”。
3 在“帐户信息”页面上,点按“国家或地区”右边的“更改国家或地区”。
4 从“选择国家或地区”菜单中,选择新的国家或地区,比如:美国。
5 下拉阅读条款与条件以及 Apple 隐私政策,两次点按“同意”。
6 在付款信息页面,付款方式选择无,付款地址找一个免税州,比如俄勒冈州(Oregon)的某地址,点按“继续”完成更改。

注:上文主要的讲的是更改国家和地区的方法;
如果是想创建美国Apple ID的话,那么还是全程美国IP,在iTunes中下载一个免费应用,按照提示操作就可以了。

解决Chrome书签管理器无法打开的问题

1 出现的问题

谷歌浏览器Chrome的扩展程序书签管理器(Bookmark Manager)在Chrome某次版本升级后就打不开了。具体情况是,点击Chrome状态栏右侧“三个竖点” > “书签(Bookmarks)” > “书签管理器(Bookmark manager)”,会出现如下提示:

eemcgdkfndhakfknompkggombfjjjeno is blocked

Requests to the server have been blocked by an extension.

Try disabling your extensions.

ERR_BLOCKED_BY_CLIENT
eemcgdkfndhakfknompkggombfjjjeno 已被屏蔽

对服务器的请求已遭到某个扩展程序的阻止。

尝试停用扩展程序。

ERR_BLOCKED_BY_CLIENT

2 解决的方法

在地址栏中输入:

chrome://flags/#enable-md-bookmarks

将默认的“Default”改为“Disabled”,重启浏览器,问题解决。
原因是Material Design书签功能目前存在bug,关闭就好了。

使用qBittorrent时遇Kernel Power 事件 ID 41 错误致windows 10 重启一例

1 问题描述

环境:windows 10 64位操作系统,博通ac网卡
之前用IDM下载文件,看电影等任何操作,一切正常。但使用qBittorrent下载种子时,短则几秒,长也不到一分钟,电脑就直接黑屏重启。且没有蓝屏错误代码出现。

2 问题分析

简要说一下排除步骤吧。

2.1 事件查看器(Event Viewer)

因为没有蓝屏代码,首先查看Windows X 系统自带的事件查看器,在Windows 日志 > 系统下,可以看到一条红色叹号图标的“关键(Critical)”错误,类似如下:

系统已在未先正常关机的情况下重新启动。如果系统停止响应、发生崩溃或意外断电,则可能会导致此错误。
The system has rebooted without cleanly shutting down first. This error could be caused if the system stopped responding, crashed, or lost power unexpectedly.
…
来源(s):       Kernel-Power
事件 ID(E):    41
级别(L):       关键

按照Kernel-Power 41 检索,发现微软有一篇技术文档来说明此问题,有点符合场景三的描述:Scenario 3: The system randomly restarts and no Stop error BugcheckCode is listed, or the computer is completely unresponsive (hard hang)。系统随机重启,且未列出关机的相关错误代码,或者电脑完全没有反应(硬件故障)。可能原因是:超频,内存问题,电源问题,过热。显然都不太是。
此外有人建议更新声卡驱动来解决这个问题,经测试无效。

2.2 Windows 10 调试工具(Debugging Tools for Windows (WinDbg, KD, CDB, NTSD))

微软提供了一个新的诊断工具:Windows 调试器 (WinDbg),我们按方法三来安装一个独立运行的版本,在安装Windows 10 SDK时仅勾选 Debugging Tools for Windows来安装。
微软该技术文档,将系统错误日志Minidump(位置在“C:\Windows\Minidump\”文件夹中)复制到桌面,打开WinDbg,在其菜单栏依次点击File > Open Crash Dump…来打开dmp文件。
待出现Bugcheck Analysis信息后,点击 !analyze -v来进一步分析错误原因。可以看到比较可疑的地方:

…
Probably caused by : bcmwl63a.sys ( bcmwl63a+8ef6f )
…
6: kd> .trap 0xffff8f805fd6a5d0
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
…

看起来是wifi驱动bcmwl63a.sys导致的问题,这是一个老生常谈的问题了。

2.3 更新WIFI驱动

出问题的Wifi网卡是博通的ac网卡BCM4352,驱动是Windows 10自带的:

驱动提供商:     Broadcom
驱动日期:       7/6/2015
驱动版本:       7.35.290.0

找到比较新的是联想提供的这个版本:

WLAN Driver (Atheros, Realtek, Broadcom) for Windows 7 (64-bit) - Lenovo B41-35, B51-35

Document ID: DS103113
Release Date: 12/28/2017

下载7gb301wf.exe并双击释放到c盘后,通过在设备管理器中右键更新驱动,并指向该文件夹来更新驱动,升级后的驱动是如下版本:

驱动提供商:     Broadcom
驱动日期:       7/20/2015
驱动版本:       7.35.295.2

打开qbittorrent测试,真的是好了一会会,没有一打开几秒钟就崩溃。但是一个多小时后问题又出现了,还是这个bcmwl63a.sys的错误。

2.4 禁用tereto(IPv6)

网上有使用bittorrent时出现该问题的情况,但更新Wifi驱动或者使用旧版驱动后问题依旧。不过在回帖中technonymous提到禁止teredo (ipv6)可解决该问题,以管理员方式运行命令行提示符,输入如下命令:

netsh interface teredo set state disabledok.

暂时正常,仍在观察中。
原因可能是因为qbittorrent等bt软件需要发送接收大量udp包,与tereto隧道兼容不好所致,尽管根本没有IPv6。微软有一篇文档提到:因为操作系统无法分配足够的堆栈空间为 UDP 数据包有许多内核过滤器 driversinstalled 时,将出现此问题。该文档中有一句:UNEXPECTED_KERNEL_MODE_TRAP,而在我的WinDbg中也有一行:6: kd> .trap 0xffff8f805fd6a5d0,不知是否有关。