IPv6与自建shadowsocks梯子

减少单一地址流量是防止服务器地址被认证的有效手段,IPv6 服务地址提供了海量地址资源,可让让自建梯更隐秘。即使v4地址已经阵亡,也可以用v6地址顶上。几种服务器端中,libev版本的配置较为复杂,其他比如Go语言、Python实现的,因为网络API已经封装好双协议监听,不需要特别配置。

shadowsocks-libev同时监听IPv4+IPv6

json 配置写法:

{
  "server":["::", "0.0.0.0"],
  ....
}

命令行写法:

ss-server -s 0.0.0.0 -s :: ....

docker 写法(mritd的影像为例):

docker run -dt --name ssv6 --network host mritd/shadowsocks -s "-s 0.0.0.0 -s :: -p 12018 -m aes-128-gcm -k mypassword --fast-open -u -6"

shadowsocks-libev出口选择IPv6优先

以前使用IPv6连打开Google容易遇上爬虫检测,现在反过来了,很多v4地址容易遇上爬虫检测。

libev版本因为DNS解释、Socket建立的过程都在程序内,所以双栈的选择需要在服务器程序配置。

json配置:

{
  "ipv6_first":true
}

命令行参数:

[-6] Resovle hostname to IPv6 address first.

Docker容器:

docker run -dt --name ssv6 --network host mritd/shadowsocks -s "-s 0.0.0.0 -s :: -p 12018 -m aes-128-gcm -k mypassword --fast-open -u -6"

注意docker的network这里用了host,是因为默认bridge的时候,如果没有给docker容器配置ipv6,会导致容器内没有ipv6资源,代理不能以ipv6往外访问。

 

客户端配置

IPv6的地址和端口的无歧义写法是这样:[2001:abcd:1234::1]:1234 ,即有中括号[]把地址包含在内。

客户端中如果是裸ss服务,不管是否用中括号都不影响,但是如果配搭KCP之类的插件,因为地址需要按参数传给kcp子进程,没有括号会导致kcp识别地址错误而失败。

因此客户端配置都推荐写上中括号。

json配置的例子:

{
  "server": "[2001:111:111::111:111:2]",
  "server_port": 12018,
  "password": "mypass",
  "method": "aes-128-gcm",
  "plugin": "",
  "plugin_opts": "",
  "plugin_args": "",
  "remarks": "lx-6",
  "timeout": 5
}

即使配置工作良好,但是Chrome浏览器在打开test-ipv6.com时候很可能还会提示:你已经有 IPv6 地址了,但你的浏览器不太愿意用,这一点比较令人担心。 主要因为Chrome对双栈策略上有fast fallback,虽然优先选择v6,但只要v6的链接建立超过0.3秒,就开始用v4去连接。所以即使完全配置正确,还是有可能撞上Google的人类检测,只能说是Google对IDC的IP段出口比较严格吧。

标签:

非主流的服务器IP地址配置

非主流一:32位掩码、网关跟网卡地址不同子网

最近新入了一台vps,看到里面的网络配置有点特别,因为按照传统理解,终端的网关必须跟地址“同段”,在同一个广播域内,才能被arp找到对应的网关MAC地址完成报文的转交。

然而这台VPS的配置是这样的,这是Ubuntu系统的网络配置文件/etc/network/interfaces

# Generated by SolusVM

 auto lo
  iface lo inet loopback

 auto eth0
  iface eth0 inet static
   address 162.xxx.xxx.247
   gateway 10.0.0.0
   netmask 255.255.255.255
   dns-nameservers 1.1.1.1 1.0.0.1

 auto eth0:0
  iface eth0:0 inet static
   address 162.xxx.xxx.248
   gateway 10.0.0.0
   netmask 255.255.255.255
   dns-nameservers 1.1.1.1 1.0.0.1
# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 00:16:3c:58:6e:ed brd ff:ff:ff:ff:ff:ff
    inet 162.xxx.xxx.247/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet 162.xxx.xxx.248/32 scope global eth0
       valid_lft forever preferred_lft forever

# ip route show
default via 10.0.0.0 dev eth0 proto static onlink 

# arp -a
? (10.0.0.0) at 00:25:90:xx:xx:xx [ether] on eth0
? (162.xxx.xxx.225) at 00:1f:12:xx:xx:xx [ether] on eth0

# arping -i eth0 10.0.0.0
ARPING 10.0.0.0
42 bytes from 00:25:90:xx:xx:xx (10.0.0.0): index=0 time=158.519 usec
42 bytes from 00:25:90:xx:xx:xx (10.0.0.0): index=1 time=196.044 usec
42 bytes from 00:25:90:xx:xx:xx (10.0.0.0): index=2 time=202.125 usec

这里的配置,居然使用了32位的掩码,然后网关地址跟vps的地址完全不在同网段(32位掩码也没有网段可言嘛),这样工作得也很正常。arp表里确实也有10.0.0.0这个“奇葩”地址的存在。

想了一下起工作原理,其实“广播域”跟IP地址是无关的,广播域是链路层的概念,只要在链路上按广播发arp(目的MAC为FF:FF:FF:FF:FF:FF),网关地址10.0.0.0只是用来让arp广播提问”who has 10.0.0.0″,确实没必要一定跟主机地址同属一个地址子网。于是这个主机就不能“局域”通信了,所有流量都要经路由器转发,也就是/32掩码的eth端口,工作起来跟ppp链路一样。

在简单环境下,路由器划分子网段时候节省了公网IP来做网关,还能避开局域网内ARP攻击带来的影响,确实有点意思。

然后顺手把配置改成用systemd-networkd管理的:

[Match]
Name=eth0

[Network]
Address=162.xxx.xxx.247/32
Address=162.xxx.xxx.248/32
DNS=1.1.1.1
DNS=1.0.0.1

[Route]
Gateway=10.0.0.0
GatewayOnlink=yes

 

非主流二:点对点链路的无下跳网关

这个其实也不算非主流,比如家里的宽带拨号后,路由器的路由表是这样的:

# ip route
default dev ppp0 scope link metric 1 
127.0.0.0/8 dev lo  scope link 
172.16.64.1 dev ppp0  proto kernel  scope link  src 172.16.97.110 
192.168.100.0/24 dev br0  proto kernel  scope link  src 192.168.100.1 

也就是没有“下一跳”的via xxx一项,不需指定,这样的网关只需要直接交给对端。

不过这里想说的是he.net提供的ipv6隧道的配置。从tunnelbroker.net提供的范例配置,其默认网关也是这种无下跳网关:

 

在把he.net的这套配置搬到systemd-netword下的时候犯了难,基本上所有的例子都是明文写了Gateway=的下跳地址。而如果留空Gateway又会报错,不写Gateway就完全不添加默认路由。手册上也没有这种特殊写法的说明

几经折腾后还是找到了方法:

# cat /etc/systemd/network/he-ipv6.netdev 
[Match]

[NetDev]
Description=HE.net Tunnelbroker sit device
Name=he-ipv6
Kind=sit
MTUBytes=1480

[Tunnel]
Local=162.xxx.xxx.248
Remote=xxx.xxx.xxx.xxx
TTL=255

# cat /etc/systemd/network/he-ipv6.network 
[Match]
Name=he-ipv6

[Network]
Address=2001:xxxxxxxxxxx/64
DNS=2606:4700:4700::1111
DNS=2001:xxxxxxxxxxxxxxx

[Route]
Destination=::/0
GatewayOnlink=yes

总结

两个非主流在配置systemd-networkd时候都用到了GatewayOnlink=yes的配置,其文档是这么说的:

GatewayOnlink=
    The "GatewayOnlink" option tells the kernel that it does not have to check if the gateway is reachable directly by the current machine (i.e., the kernel does not need to check if the gateway is attached to the local network), so that we can insert the route in the kernel table without it being complained about. A boolean, defaults to "no".

其实就是ip addr via xxx onlink里面的onlink。

至于我为啥那么执着于systemd-networkd,这正是我最想吐槽的地方。

Linux下管理网络配置的组件很多,以前各个发行版都有自己的一套配置,rh系原生使用/etc/sysconfig/network-scripts/ifcfg*的纯脚本变量配置,但是为了配合桌面环境,引入了NetworkManager;debian系原生使用/etc/network/interfaces ,配合桌面环境,也引入了NetworkManager;本来殊途同归吧,但是NetworkManager这货太复杂了,绝大多数功能都是为了桌面应用(比如适配3G4G无线网卡、蓝牙共享网卡、手机插线上网…),在仅需要简单配置网络的环境常常成为碍事的东西;而systemd逐渐成为各大发行版的标配,用systemd-networkd配置服务器网络看起来是最合适、最通用的。然而,Ubuntu并不这么认为,为了兼容systemd-networkd和NetworkManager,不嫌麻烦更在最近的版本里面更引入了个叫做netplan.io的项目……学不动求不更!

 

所以不管什么发行版,只要不是做桌面的机器,我一律清理那些琐碎配置组件,用systemd-networkd统一接管:

#ubuntu 18.04
apt remove -y resolvconf netplan.io nplan network-manager ufw
apt install -y iptables-persistent
rm /etc/resolv.conf
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
systemctl disable networking
systemctl enable systemd-networkd
systemctl enable systemd-resolved

##各种配置

#Fedora/CentOS7

yum/dnf erase NetworkManager firewalld
yum/dnf install -y iptables-services iptables-nft iptables-utils

 

 

 

标签: , , , , ,

dnsmasq导致caddy更新letsencrypt DNS-01 挑战失败

自从宽带有IPv6,家里的NAS上就跑着caddy来走https代理一些本地服务。caddy能自动申请和维护更新let’s encrypt的证书,非常方便,但是最近发现日志上,caddy无法更新到证书。

/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/Caddyfile -root=/var/tmp
Activating privacy features...
2018/11/23 12:07:22 [INFO][xxxx.ptsang.net] acme: Obtaining bundled SAN certificate
2018/11/23 12:07:23 [INFO][xxxx.ptsang.net] AuthURL: https://acme-v01.api.letsencrypt.org/acme/authz/.
2018/11/23 12:07:23 [INFO][xxxx.ptsang.net] acme: Could not find solver for: http-01
2018/11/23 12:07:23 [INFO][xxxx.ptsang.net] acme: Could not find solver for: tls-sni-01 
2018/11/23 12:07:23 [INFO][xxxx.ptsang.net] acme: Trying to solve DNS-01
[xxxx.ptsang.net] dns cloudflare failed to get certificate: Could not find the start of authority

因为let’s encrypt还不能访问纯IPv6地址的服务器,所以只能按DNS-1 Challenge方式验证。这是使用了caddy的cloudflare DNS插件,问题主要是”Could not find the start of authority”。

caddy是开源的,所以去github找到他的cloudflash校验源码,搜索到这句提示是这里返回的。看了一下逻辑,应该是DNS去查询SOA记录,查到了就返回,查不到就报这个错误。

于是用命令行的dig测试一下,果然没有。。

[email protected]:~$ dig +short SOA ptsang.net

#直接指定外网DNS服务器试试
[email protected]:~$ dig +short SOA ptsang.net @1.1.1.1
duke.ns.cloudflare.com. dns.cloudflare.com. 2029463065 10000 2400 604800 3600

居然是路由器上的DNS问题?检查了下路由器上dnsmasq的配置,发现有一句filterwin2k :

-f, –filterwin2k  Later versions of windows make periodic DNS requests which don’t get sensible answers from the public DNS and can cause problems by triggering dial-on-demand links. This flag turns on an option to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the requested name has underscores, to catch LDAP requests.

从名字看似乎是个有些年头的功能了,说win2000时候会周期性查询外网DNS,而导致自动拨号,所以用这个开关来过滤掉SOA、SRV和含有下划线的域名请求…

Dnsmasq主要是家用路由器上使用,一般环境应用也不会用到这类记录,所以原来开不开都没啥感觉,最近刚好给路由器刷了ROM,这些参数默认带上了。而现在let’s encrypt是需要校验域名的SOA (Start of Authority)记录的,于是踩坑成功… feature变bug。

Caddy一般都是在服务器上用,极少遇到这种情况(用DNS Challenge的应该都是比较小众了)。唯一google到一个类似的问题是在caddy的社区,这个楼的问题是刚刚把域名从linode转移到了cloudflare,SOA记录还被边沿DNS服务器缓存中,所以校验失败…

标签: , , ,

au home spot cube (RTL8196C) 无线路由的微调参数备份和恢复

au home spot cube是几年前日本KDDI公司配套给用户的设备,大概2015年时候估计换设备,这个小东西就变成洋垃圾大批量地进入了国内。到现在,淘宝上只需要不到15元一个,如无意外是市面上性价比最高的5G双频路由器。

我弄了两台回来当玩具,折腾两天的结论是,用来当AP做5G Wifi接入,还是挺稳挺靠谱的,其他各种折腾不大值得花时间。首先是硬件配置较低,32M RAM+8M Flash基本就断了开发多用途的念想,然后是RTL8196C主控+RTL8192DR无线的配置,没什么社区支持的力量…

小路由器主要的折腾资源都在恩山论坛的帖子。有Realtek的芯片SDK版本的ROM,以及一些其他品牌的移植。不过使用评价上,基本上所有ROM都不令人满意的,首要问题就是5G信号远没有官方ROM强。

官方SDK我测试过还可以,但是因为缺乏定制脚本的原因吧,比如硬件AP/Router模式的选择按钮无效、WPS无效、每次重启模式固定为网关,无法保存..等等小问题,并不实用。然后刷回别人提供的原版编程器固件,欸,好像信号也并没有恢复原状。

经过研究,不同版本的硬件对无线信号是有微调参数的,刷机后微调参数变成别人版本的参数,如果参数区别较大,就会出现信号不好的情况。幸好开始折腾前我把flash内的配置都导出了到文本中保存起来了。【[Embedded System] 手動設定 Calibration Power】。

主要是有TX_POWER字样的键值,用grep命令过滤后得到需要还原的数据。(下面代码我删除了很长的输出)

$ grep -i tx_power auhome_a66NRc_orig_all.txt > auhome_xxx_txpower.txt
$ cat auhome_xxx_txpower.txt
HW_WLAN0_TX_POWER_CCK_A=...
HW_WLAN0_TX_POWER_CCK_B=...
HW_WLAN0_TX_POWER_HT40_1S_A=...
HW_WLAN0_TX_POWER_HT40_1S_B=...
HW_WLAN0_TX_POWER_DIFF_HT40_2S=...
HW_WLAN0_TX_POWER_DIFF_HT20=...
........

最重要一点,还需要把16进制数据转换成10进制输入,以及一些结尾0值要清理否则flash命令会segmentation fault … 如果手工算那真是体力活啊,这时候要体现码农垃圾佬的价值了:

#!/usr/bin/env python3
with open("auhome_xxx_txpower.txt") as f:
    for line in f.readlines():
        line = line.strip()
        key, val = line.split('=')
        
        #每2位十六进制数转换成十进制
        decvals = [
                int('0x'+val[i:i+2], 16)
                for i in range(0, len(val), 2) ]
        olen = len(decvals)
        
        #全0的字段可清空
        if not any(decvals):
            decvals = []
            
        #结尾的0可清空
        while len(decvals) > 1 and decvals[-1] == 0:
            decvals.pop()
        
        #清除过结尾0的值最后加1个0值
        if len(decvals) < olen:
            decvals.append(0)
            
        strvals = map(str, decvals)
        
        #打印写入命令
        cmd = "flash sethw {} {}".format(key, " ".join(strvals))
        print(cmd)

因为数据太长了,web管理里面的syscmd.asp中无法输入处理(短的几条还行),还是在TTL线终端里面粘贴进去(一次性还不能复制太多行,会导致死机,一次三四行那样吧)。把路由器重启后,信号果然就恢复如初了。

其他的折腾思路可以是把官方ROM中检测模式开关,启动脚本等地方完善,然后把初始ROM的5G微调数据写入SDK版本ROM中,理论上是能够完美使用的… 不过个人觉得不大值得这个折腾…还是用官方吧!

PS:部分控制参数的含义整理

 AP物理参数

#以下参数参考了github中rtl8192的源码中的定义
#https://github.com/pvaret/rtl8192cu-fixes

#双频共存 默认:1
#仅使用5G可设置成0
flash set WLAN0_COEXIST_ENABLED 0 

#WIfi物理频点分配模式  默认:2
#   0:SINGLEMAC_SINGLEPHY 单MAC单链路
#   1:DUALMAC_DUALPHY 双MAC双链路
#   2:DUALMAC_SINGLEPHY 双MAC单链路
#   改成1最高链接可达300M,但是因为有线网口是100M的,测不出区别
flash set WLAN0_MAC_PHY_MODE 1

#空时编码(sTBc)发射分集技术  默认:0 
#   理论上有用但是实测不出来有什么区别
flash set WLAN0_STBC_ENABLED 0

#BEAMFORMING技术:默认0 
#   保持关闭就好,因为BEAM不同网卡支持有兼容问题)
flash set WLAN0_TX_BEAMFORMING 0

频带与区域

#频带区域 似乎没实际意义,是让wlbasic.asp的网页的js显示出36/149高低段频带
# 源码内有全部的参数的定义,其中中国区域对应应为12
# https://github.com/pvaret/rtl8192cu-fixes/blob/756f2ec582b3861c033214effb511ec27aed9938/include/rtw_mlme_ext.h#L103
# 实际使用中中国的合法频带是比较多的,其实兼容各种配置
flash sethw HW_WLAN0_REG_DOMAIN 2

#实际频道,40M低可选36 / 44 / 149 / 157 / 165
flash set WLAN0_CHANNEL 149

#频带捆绑,即开启40M,使用相邻两个频段,默认1
flash set WLAN0_CHANNEL_BONDING 1

#控制信道处于上/下,默认1,1=Lower  0=Upper
flash set WLAN0_CONTROL_SIDEBAND 1

#虚拟AP2的开关
#  本来应该无关紧要的,VAP2是一个KDDI公司设置的调试虚拟AP
#  但是如果设置为1关闭,会导致5G AP能连上能获取IP但是就不能上网通信,神奇BUG(也许跟ROM系统内br1桥有关)
#flash set WLAN0_VAP2_WLAN_DISABLED 0

5G频段兼容性

因为历史原因,中国在2014年修订了民用无线电频段标准后,5G可用的可用频段增加了很多;然而很多在2014之前生产的网卡/驱动,都没跟的上更新,特别Windows自带的驱动往往无法看到36/44频段之类的现象。比如淘宝很常见卖不到30元的AR5B22 / AR9462,传说中Killer卡(并不是),都是属于这类。但是强制给windows安装上对应芯片的新版启动,却工作得很好。有个高通网卡驱动的网站收集得非常齐全

另外发现我的AR5B22 网卡无法连接CONTROL_SIDEBAND 为Upper的设置,Windows会强制重置网卡。无解。

标签: , ,

VMware EXSI 6.5/6.7独立主机手工升级补丁包

VMware EXSI 6.5后有免费授权,对于8核以内的主机都免费使用。这对一般个人用途的虚拟环境完全够用。不过EXSI系统本身也是需要升级维护的,我就遇到了一个跟ubuntu系统网卡性能的BUG,要升级EXSI核心来解决。EXSI的升级维护官方途径,可以当官方发布新的ISO时候重新运行安装程序来升级,又或者用一个Update Manager的服务,是属于vSphere的一个组件… 免费授权是不包括这些高大上的东西的,但是可以简单地敲命令滚动更新。

EXSI SSH

主机-操作-服务-启动安全Shell(SSH)即可启动EXSI自带的ssh服务,直接用root密码登入。

里面的环境跟linux基本类似,但是升级之类的操作是通过esxcli 命令操作的。

升级包

EXSI不是像Linux发行版办那样维护一个固定的软件源来维护更新,有个第三方的网站VMware ESXi Patch Tracker 定期追踪esxi发布的补丁包。Web界面上存在一个允许输入vib安装包的地址的窗口,但是一般每个补丁包都包括多个vib,而有些vib也有版本依赖之类的,手工解决显然不靠谱。

比如,从https://esxi-patches.v-front.de/ESXi-6.5.0.html看到目前最新是ESXi-6.5.0-20181103001-standard补丁包,点击后出现小窗口:

【下面代码会过时,请看Tracker的最新发布】

# Cut and paste these commands into an ESXi shell to update your host with this Imageprofile
# See the Help page for more instructions
#
esxcli network firewall ruleset set -e true -r httpClient
esxcli software profile update -p ESXi-6.5.0-20181103001-standard \
-d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml
esxcli network firewall ruleset set -e false -r httpClient
#
# Reboot to complete the upgrade

就3个命令,复制粘贴到EXSI的SSH,执行完后就是升级好了。3个命令其实只有中间的是升级,前后的是临时开启防火墙规则,允许升级程序访问外网。

问题和踩坑

嗯重点来了,如果直接复制粘贴就那么容易搞定就没必要写篇BLOG了。上面的几个命令很可能报错不能执行的。

首先首先要找到详细日志。命令执行的时候完全是静默的,但是后台活动很多,多登陆一个ssh窗口,可以查看/var/log/esxupdate.log的输出,有less/tail/cat等命令使用。

空间不足

我遇到第一个问题就是日志里面出现空间不足的问题。

2018-08-01T03:15:55Z esxupdate: 2107709: vmware.runcommand: INFO: runcommand called with: args = 'localcli system visorfs ramdisk add -m 0 -M 187 -n vibdownload -p 755 -t /tmp/vibdownload', outfile = 'None', returnoutput = 'True', timeout = '0.0'.^@
2018-08-01T03:15:55Z esxupdate: 2107709: HostImage: INFO: Attempting to download VIB tools-light^@
2018-08-01T03:15:55Z esxupdate: 2107709: downloader: INFO: Downloading https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/esx/vmw/vib20/tools-light/VMware_locker_tools-light_10.2.1.8267844-8941472.vib to /tmp/vibdownload/VMware_locker_tools-light_10.2.1.8267844-8941472.vib^@
2018-08-01T03:19:58Z esxupdate: 2107709: vmware.runcommand: INFO: runcommand called with: args = 'localcli system visorfs ramdisk list | grep /vibdownload && localcli system visorfs ramdisk remove -t /tmp/vibdownload', outfile = 'None', returnoutput = 'True', timeout = '0.0'.^@
2018-08-01T03:19:58Z esxupdate: 2107709: HostImage: ERROR: Failed to send vob install.stage.error: [Errno 28] No space left on device^@
2018-08-01T03:19:58Z esxupdate: 2107709: vmware.runcommand: INFO: runcommand called with: args = 'localcli system visorfs ramdisk list | grep /stagebootbank && localcli system visorfs ramdisk remove -t /tmp/stagebootbank', outfile = 'None', returnoutput = 'True',

跟踪了一下上下文,原来他的升级程序是根据物理内存按比例建立一个临时内存盘,把补丁包下载到内存盘中再使用的。然而我的垃圾机器只有4G内存,临时内存盘自然也小得可怜,放不下他的补丁包了。

PS: 原来EXSI里面的维护程序跑的是python3.5。

深挖后发现可以增加“本地交换”区来处理,在Web上【主机】-【管理】-【系统】-【交换】-【编辑设置】内选择本地硬盘的datastore,并启动本地交换和主机缓存,再升级时候就顺利了。

网络不通

有些情况是EXSI本身所处的网络是不通外网的,需要走一个内网的HTTP代理才能链接。在vSphere文档查询了一下,software profile update 有个-p参数是可以指定代理的。

esxcli software profile update -p ESXi-6.5.0-20181103001-standard \
--proxy http://192.168.123.161:3128 \
-d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml

然而并不行。

通过日志发现是连接内网超时了…是EXSI的防火墙并不允许访问3128端口,需要设置特定规则来允许…又或者,直接把防火墙关掉。

esxcli network firewall unload

嗯,很暴力,但是不用怕,重启主机后会一切如常的,不放心的话就load回来就好(unload改成load)。

 

标签: , ,

Win10 – WSL 使用小贴士

此前多年我都是信仰级的Linux User,不过后来因为工作硬件支持的原因,级别掉到佛系user,有什么用什么。更因为Win10加入了WSL的功能后,开发环境已经足够使用。

对于WSL我几乎是第一批使用的用户,那时候才2015年。Win10 持续更新到现在(1809),WSL环境下总体已经没什么有影响体验的问题了,作为一般的开发环境绝对够用。这里分享下在较新的WSL下依然需要tune的细节。

终端

Windows下的终端一直都是弱项,这都8102年了,cmd都没有类似bash下.profile、.history之类的几十年以来都有的功能。不过WSL里面有bash,就没cmd.exe什么回事;然而,默认启动的wsl,似乎还是cmd.exe的窗体?

还好有第三方终端。有个比较出名的ConEmu,多年以前都是win下终端的首选替代品了,功能也很多,也支持了WSL。不过我不大喜欢,量级略重,启动慢,我日常使用的是wsltty

wsltty是两个小项目:mintty和wslbridge的捆绑发行版,加起来也是几百k的体积,使用时启动非常快,就像linux桌面下启动xterm。

功能也没花俏,就一个“终端该有的样子”。

工作原理上,wslbridge跑在WSL里面运行了shell,然后把stdin/stdout/stderr用管道传给win下的窗体程序mintty,所以比起在wsl内跑sshd,再用ssh客户端链接的方案要方便快捷很多。

Ubuntu

WSL内的发行版我现在是用Debian的,因为比起Ubuntu,默认安装上要更为“轻量”,更重要的是使用Debian unstable的发行有滚动更新,能跟上很多软件包的最新版本。

Ubuntu的重量级体现在其默认安装了很多“友好的工具”。大家应该不陌生在Ubuntu下敲了错误的命令、不存在命令时候,终端提示不是冷冰冰的command not found,而是友好地提示:这个命令没有安装呢,请安装xxx软件包,命令如下;又或者在xxx、yyy、zzz软件包有类似的命令……

但是在WSL Ubuntu下,这个体验就不大友好了,敲错命令了,终端会卡死几秒钟……然后才出现上述的提示。终究原因,还是因为WSL的磁盘IO性能比较差,而ubuntu提供这个提示功能的是有专门的程序在数据库里面搜索一通才完成的,而且这个程序是还Python写的。一个错误命令扯起一套环境读入、读库搜库,即使是SSD硬盘,都能卡上几秒……我宁愿要冷冰冰的command not found.

删掉Ubuntu的预装包就好了:

sudo apt remove python3-commandnotfound command-not-found command-not-found-data

而Debian默认是不会安装这类玩意的,轻量级的跑起来很快。甚至太轻量了,连查文档的man命令都是没有的:

sudo apt install man-db

WSL运行其他发行版

Win10商店内目前只有Ubuntu/Debian/Suse以及一个收费版本WLinux等发行版,选择性还是有点限制;而且,从商店安装的版本只能安装在C盘很深很深的目录,类似%LOCALAPPDATA%\Packages\TheDebianProject.DebianGNULinux_123456789abcd\LocalState\rootfs\home\user这样的目录。

不过开源社区有别的选择,wsldl项目可让其他发行版也作为wsl安装到Win10内,仅仅是解压运行exe,而对应发行版的rootfs就解压到exec的目录。也就是说解压到D:\Archlinux,运行D:\Archlinx\Arch.exe后,Arch就安装到D:\Archlinux\rootfs了。比起用商店安装更方便!

类似的可选发行版还有Arch ,ArtixAplineCentos

服务

如今很多发行版都使用了systemd做服务管理,然而WSL下systemd是不可能跑起来的。当然现在社区都正在为支持WSL努力,不过在可用之前,似乎没什么好办法。

比如安装了mysql,想要启动起来,只能手工地在screen里开个终端运行mysqld。WSL目前对后台确实缺乏友好。

一个方法是把服务管理系统改回SysV之类,但总感觉是伤筋动骨了,目前我没什么好的办法,只能是使用的时候在screen/tmux挂一个专门跑服务进程的终端。

微软的商店里上线了个叫做WLinux的发行版,也是基于Debian的,售价20刀。据说是专门给WSL环境优化的系统环境,完全没有systemd,理论上应该解决这个头痛的问题了。当然作为开源产品,付钱购买不是必须的。不过我还没实践过,可能需要用到这个可以安装任何发行版到WSLLxRunOffline 。不过WLinux的特点是结合linux环境的GUI工具和win下的X-Server配合,重量级的配合,不是我的菜。

VSCode开发集成

WSL存在的价值就是开发环境,所以跟开发工具是离不开的。开箱可用的Visual Studio Code编辑器也成为近来最爱,不过在WSL的支持上,开发者们还在努力。

VSCode默认是支持git的,但是他用的是windows环境的git,WSL里面也有git,虽然都安装的话两套git也能完成代码管理,但是总有点突兀(主要是刷新状态上)。

有个叫wslgit的项目,直接把WSL里面的git“翻译”成原生git,只需要WSL里面配置一下就可以了。

{
    "git.path": "C:\\Users\\xxx\\bin\\wslgit.exe"
}

VSCode里面也集成了终端功能,运行代码时候不用跟终端程序切换的,按ctrl+`就可以,然而默认打开的是cmd.exe,顺便改一下。

{
    "git.path": "C:\\Users\\penti\\bin\\wslgit.exe",
    "terminal.integrated.shell.windows":
         "C:\\Windows\\System32\\bash.exe"
}

其他还有Python/Node这类环境都可以在VSC里面直接调用WSL里面的代码的,其实主要就是处理了Win下D:\Path到WSL内/mnt/d/Path这类的映射问题。更多WSL的增强辅助项目,可查看WSL-Awesome内列出的一堆项目。

 

编辑历史:

2018-11-19:第三方发行版支持部分内容。

OPENSSL/Tomcat Keytool命令小抄

OPENSSL自签证书一行流

#CN=Common Name,web服务器中所用的域名
#O=Organization,签名机构名称
#C=Country,国家地区
#days 3650,证书10年有效

openssl req -subj '/CN=domain.com/O=My Company Name LTD./C=CN' -new -newkey rsa:2048 -days 3650 -nodes -x509 -keyout server.key -out server.crt

OPENSSL查看信息

#PEM证书信息
openssl x509 -in server.crt -text -noout

#P12证书信息
openssl pkcs12 -info -in server.p12

OPENSSL对证书校验

#输出结果应完全一致
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
openssl req -noout -modulus -in server.csr | openssl md5

Tomcat用的keystore格式跟pem转换

PEM 转 Keystore

#注意较新版本的tomcat要求直接用p12格式,省略转keystore一步。

#先转换为证密二合一的p12格式文件,注意密码要跟下一步一致,p12的name将成为ks的alias
openssl pkcs12 -export -inkey server.key -in server.crt -name root -out server.p12

#导入到keystore
keytool -importkeystore -srckeystore server.p12 -srcstoretype pkcs12 -destkeystore server.ks
TOMCAT 配置

修改tomcat/conf/server.xml

<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="path/to/server.ks" keystorePass="password"
           clientAuth="false" sslProtocol="TLS"/>

 


Keystore 转 PEM

#先查看keystore内的srcalias对应需要的证书,
keytool -list -v -keystore server.ks

#比如上命令看到 Alias name: root
#选择特定的证书(srcalias)转换成pkcs12格式
keytool -importkeystore -srckeystore server.ks -destkeystore serverks.p12 -srcalias root -srcstoretype jks -deststoretype pkcs12

#从p12提取出证书
openssl pkcs12 -in serverks.p12 -clcerts -nokeys -out serverks.crt

#从p12提取出私钥(必须设置私钥密码)
openssl pkcs12 -in serverks.p12 -nocerts -out serverks.key

#去除私钥文件的密码
openssl rsa -in serverks.key -out serverks_plain.key
#注意从p12转出的文件一般都带有Bag Attributes等一些信息行,可能在特定程序引起不兼容,注意需要手工编辑清理

标签: , , , , ,

本博客的网络结构

话说这个博客现在的网络结构是这样的。

 

其实这个博客除了写东西记录,另外就是我尝试部署技术的一个练习场。虽然之前内容上已经长草了多年,不过后台技术其实一直有变化的呢。

最近把博客后台结构折腾成上图那样了。内容服务器放墙内腾讯云,因为:

  • 廉价主机:此前腾讯云推广活动,300元撸了6年的主机,比起在墙外各处小机间不断迁移,固定到一个主机似乎更好选择。
  • 性价比高:腾讯云这个主机配置虽然不高,但是比起一众同价位的墙外VPS还是好不少,用来跑docker相当不错。

然而缺点显然也有:

  • 未备案站点不能在墙内服务,HTTP流量会被多重检查劫持。
  • 因为选了最大服务时长,腾讯云的带宽只开到最低的1M。

这样的配置一般来看就很鸡肋了,只能刷一个存在。不过正在国内各种云服务刷活动,费率都不低,人家Cloudflare的CDN可是全免费的!然而Cloudflare要做到缓存加速、内容优化,回源流量都需要走明文的HTTP,而墙内主机是不行的。

于是给几台爬墙用的海外VPS配置上了Wireguard做前端服务。Wireguard的实现非常优雅,在Linux上都不需要服务进程(倒是要内核模块)。腾讯云主机虽然有公网IP,但是他的网络结构是NAT进去的,之前想过使用IPv6 teredo等技术播一个V6 IP进去实现同样的功能,但是考虑到隧道只负责封装,不负责加密,可能还是会撞到国内运营商的重重流量墙,于是还是Wireguard方案了。

后端wordpress自然是跑PHP的,从当初的php-fpm+nginx,后来尝试过uwsgi-php + nginx,然后用caddy替换了nginx,HTTPS的证书问题很舒服。后面用docker就没拘泥这些细节了,直接部署了docker全家桶,配合cloudflare很是省心了。

以上。

Top