使用 Shadowsocks-libev 构建网络代理

1. 序

作为一个程序员,总有着一些科学上网的需求。面对纷繁的服务提供商,面对时断时续的网络服务,总还是觉得老话说的有道理:自己动手丰衣足食!

2. 搭建过程

搭建代理服务器的常见手段是在一台境外服务器上启动 Shadowsocks 服务,然后在终端使用客户端连接过去。大致过程可以分为几个简单步骤:

  1. 购买境外服务器。

  2. 搭建 Shadowsocks 服务。

  3. 下载客户端连接。

2.1 购买服务器

在同事的推荐下,在 Vultr1 购买相关的服务。配置和价格如下:

项目 规格
CPU 1 vCore
RAM 1024 M
Storage 25 G SSD
Bandwidth 1000 GB
Location Silicon Valley
OS Ubuntu 18.04
Price $ 5 /month

但就价格来说每年对应人民币在 400 元左右价格偏贵,但是如果考虑到同时能搭建 WordPress 和 Shadowsocks 服务的话相对更容易接受一些。

另外一个好处是灵活,如果这个 IP 被封了还可以在其他地区的机房搭建服务。

2.2 搭建服务

搭建服务只需要按步骤执行如下命令(默认 root 用户)2

 apt-get update
 apt-get install -y shadowsocks-libev

然后编辑配置文件 /etc/shadowsocks-libev/config.json

 {
     "server":"0.0.0.0",
     "server_port":<port>,
     "local_port":1080,
     "password":"<password>",
     "timeout":60,
     "method":"aes-256-cfb"
 }

这里 <server port><password> 根据喜好设置即可。

然后我们启动服务:

 # 重新启动 shadowsocks-libev (以防按照旧的配置启动了服务)
 systemctl restart shadowsocks-libev
 
 # 设置随着操作系统自启动
 systemctl enable shadowsocks-libev.service
 
 # 查看服务状态
 systemctl status shadowsocks-libev.service

另外针对网络拥塞的情况我们还可以使用 BBR 来提升网速,具体的方法为3

 echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
 echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
 sysctl -p

关于 BBR 的原理可参见参考资料4

2.3 下载客户端

Shadowsocks 的客户端可以从 Github 进行下载,具体页面为:

3. 参考资料

使用 Docker 构建工作环境

1. 前言

作为一个程序员,在家加班或者处理紧急需求是一种常态。为了应对这种情况(也为了更好地压榨程序员的剩余时间)大部分公司都会给员工配发笔记本电脑。

新员工入职第一件事情就是配置工作环境,这个工作至少耗费一天的时间。有经验的程序员一般会用一个 dotfile 项目来保存常用的配置文件,比如 .zshrc.vimrc.ssh/config 等。

本文更进一步,使用 Docker 来构建工作环境。

原因在于以下几个方面:

  • 任意电脑都可以快速初始化工作环境。本人不喜欢把公司电脑背回家,一来太重太麻烦,而来丢了坏了还要找你赔。

  • 隔离工作环境。把工作环境当做不同的 profile,以插件的形式加载到环境中,灵活而且干净。

2. 实施方案

为了更好地保障安全性,本人把工作环境的 Docker 分为两个部分:

  • Docker 镜像

  • dotfile (Git 仓库)

本质上是代码和配置分离的策略,镜像可以使用阿里云提供的服务来存储,而 Dockerfile 和 dotfile 则利用 Git 的私有库做版本控制和多机器同步。

2.1 Docker 镜像

以下是本人人生中第一个 Dockerfile:

 ARG UBUNTU_VERSION=18.04
 FROM ubuntu:${UBUNTU_VERSION}
 MAINTAINER wuzhiyu "wuzhiyu@avalon-inc.com"
 
 ###################### SYSTEM SETTINGS ######################
 
 ARG USER_NAME=<account name>
 ARG GROUP_NAME=sudo
 ARG PASSWORD=<password>
 ARG HOME=/home/${USER_NAME}
 ARG HOST_NAME=ubuntu-docker
 
 # 1. update chinese software repository
 RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak
 COPY 18.04.aliyun.sources.list /etc/apt/sources.list
 
 # 2. install necessary software
 ENV DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y sudo man curl inetutils-ping git tmux vim autojump python-pip zsh oathtool expect && apt-get clean && pip install mycli virtualenv virtualenvwrapper
 RUN apt-get update && apt-get install -y locales && apt-get clean && locale-gen en_US.UTF-8
 
 # 3. (1)create a user account without password (2) grant sudo permission by adding account to sudo group (3) set password for the account
 
 RUN adduser --home ${HOME} --ingroup ${GROUP_NAME} --shell /bin/bash --disabled-password --gecos "" ${USER_NAME} && echo "${USER_NAME}:${PASSWORD}" | chpasswd
 RUN chown -R ${USER_NAME}:${GROUP_NAME} ${HOME}
 
 ###################### USER SETTINGS ######################
 
 # set default user and work dir
 USER ${USER_NAME}
 WORKDIR ${HOME}
 ENV USER ${USER_NAME}
 
 # install oh-my-zsh
 RUN export RUNZSH=yes && sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
 
 # config-files -v when docker run
 
 # CMD
 CMD /usr/bin/zsh

这个 Dockerfile 干的事情非常简单,简单来说就是:

  1. 指定基础镜像。

  2. 更新 Ubuntu 的软件源。国情在此,用阿里云的替换。

  3. 使用非交互模式安装必要的软件。

  4. 创建用户账户并授予 sudo 的权限。

  5. 切换到用户账户和家目录。

  6. 安装 oh-my-zsh

  7. 指定默认进入 zsh

构建命令为:

 docker build -t workspace:latest ubuntu

其中 ubuntu 是保存 Dockerfile 和其他文件的上下文目录。

看的出来镜像本身是比较简单的,主要是准备必要的软件和运行账户,下面来介绍一下 dotfile。

2.2 dotfile

dotfile 项目包括不限于以下内容:

  • .zshrc

  • .vimrc

  • .ssh/config

  • 公钥私钥

  • 业务脚本

2.2.1 .zshrc

这个文件是 zshell 启动时默认加载的文件,一般也是我们所有环境配置的公共部分。我们可以通过一些命令来判断加载特定的 profile。

比如:

 # 为 true 表示为 Mac 环境
 [[ $(uname) = "Darwin" ]]
 
 # 为 true 表示为 Docker 环境
 [[ -f /.dockerenv ]]

如果为 docker 环境,我们可以 source 包含业务信息的脚本(比如自动进行两步校验的登录脚本、包含数据库连接串信息的脚本等等),也可以进行环境配置文件的自动更新。

2.2.2 .vimrc

Vim 的配置文件,此处不表。

2.2.3 .ssh/config

常见来说两种使用功能:

  • 自动指定跳板机或端口信息

  • 对应特定应用使用特定私钥

首先一般公司内部连接线上服务器都要求通过指定的跳板机和特定端口(非默认 22)来连接,每次指定自然非常繁琐,通过 .ssh/config 文件则可以大大减轻负担。

 Host *.dev
     HostName %h.xxx.com
     User wuzhiyu
     Port 10086
     ProxyJump <gateway>
     IdentityFile <path_to_private_key>

一般来说,如果我们要连接 master01.dev.xxx.com 这台机器一般要先跳到跳板机,然后使用如下命令:

 ssh -i <path_to_private_key> wuzhiyu@master01.dev.xxx.com -p 10086

但是有了上述配置,我们可以写作:

 ssh master01.dev

跳板机、端口、机器后缀、私钥位置自动带上了。

2.2.4 公钥私钥

接上文,对于不同的版本控制系统使用不同的密钥是很常见的一种场景。比如公司内部用一套密钥,个人 GitHub 账户使用另外一套,把公司的密钥放在 dotfile 私有库进行同步便于配置的保存与迁移。

2.2.5 业务脚本

比如数据库连接串的别称、自动登录脚本等,不再赘述。

3. 实践使用

Docker 运行的时候可以使用如下命令进行启动:

 docker run -it --rm -h docker --network host -v <path_to_dotfile_dir>:/home/wuzhiyu/.config-files:ro -v <path_to_zshrc_file>:/home/wuzhiyu/.zshrc:ro --name workspace workspace:latest /usr/bin/zsh

这里有几点要注意:

  1. 网络模式使用了 -—network host 模式是为了使用宿主机的 VPN 网络。

  2. 加载的时候直接挂在了 .zshrc 文件,这样容器运行 zshell 的时候就可以直接加载初始化的脚本。

  3. 默认指定一下 HOST 名称否则部分软件运行会报错。

TMUX 自定义配置

QQ20160703-0
TMUX 号称是文本处理的“三大神器”之一,不是没有理由的。最近工作上好多事情都要在服务器上处理,所以用 TMUX 特别频繁。

最近花了点时间自己配置了一下 TMUX,这里权当记录一下吧。

1. 自动加载配置文件

在使用 TMUX 的时候,如果要重新加载配置文件,需要 Ctrl + b 触发,然后输入 : + source-file + ~/.tmux.conf

因为在调试配置的时候需要反复尝试,所以把这个配置做成了快捷键 Ctrl + b + R

bind R source-file ~/.tmux.conf

2. 采用 Vi 模式的快捷键

开启之后在复制模式(copy-mode,Ctrl + b + ?)中可以使用 Vi 模式下的快捷键。

setw -g mode-keys vi

3. 鼠标支持

对于鼠标的支持表现在通过鼠标的点击切换 window、pane 以及通过拖曳更改 pane 的大小。

注意的是 TMUX 版本的不同设置方式也不同。我的 MacBook Pro 使用的是 2.1,而我经常登录的服务器上使用的是 1.6。查看 TMUX 版本的命令是:

tmux -V

如果是 2.1 的话,设置为:

set -g mouse on

如果是 1.6 的话则设置为:

set -g mouse-select-window on
set -g mouse-select-pane on
set -g mouse-resize-pane on

4. 切换 pane 的快捷键

默认的设置中,pane 的切换的快捷键是 Ctrl + b + 方向键,为了更便捷地进行切换,定义了新的快捷键 Alt + 方向键

# 切换为使用 Alt-方向键 切换同一 Window 中的pane
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

5. 自定义状态栏

TMUX 可以自定义状态栏的颜色和展示信息。首先给出我暂时使用的配置:

# 自动重新编号 window
set -g renumber-windows on

# 设置自动刷新的时间间隔
set -g status-interval 1
# 状态栏左对齐
set -g status-justify left
# 状态栏左侧宽度
set -g status-left-length 20
# 状态栏右侧宽度
set -g status-right-length 50

# 状态栏背景颜色
set -g status-bg '#333333'
# 状态栏前景颜色
set -g status-fg '#ffffff'
# 状态栏左侧显示 session 的名字
set -g status-left '#[bg=#00bb00] [#S] #[default] '
# 状态栏右侧显示时间
#set -g status-right '#[fg=white,bg=#55bb00] [#h] #[fg=white,bg=#009c00] %Y-%m-%d #[fg=white,bg=#007700] %H:%M:%S '
set -g status-right '#[fg=white,bg=#444444] [#h] #[fg=white,bg=#666666] %Y-%m-%d #[fg=white,bg=#888888] %H:%M:%S '

# 当前激活窗口在状态栏的展位格式
setw -g window-status-current-format '#[bg=#ff0000, fg=#ffffff, bold]*[#I] #W*'
# 未激活每个窗口占位的格式
setw -g window-status-format '#[bg=#0000ff, fg=#ffffff] [#I] #W '

有几个配置需要进行说明一下:

5.1 关于时间的配置

上文配置中,我采用了几个时间参数显示在了状态栏的右侧:

参数形式 参数含义
%Y 年:2016
%m 月:07
%d 日:03
%H 小时:02
%M 分钟:19
%S 秒:04

需要注意的是其实这个时间的刷新是有间隔的,我们可以通过设置参数:

set -g status-interval 1

使得状态栏的时间好像每一秒都在变化。

5.2 颜色配置

TMUX 的状态栏中可以按照 #[bg=colourxx,fg=#ffffff] 的形式定义颜色的前景和背景。颜色的类型指定如:blackredgreenyellowbluemagentacyanwhite 。也可以是 colour0 到 colour255。或者形如 #ffffff 的 RGB 格式。同时还可以针对字体进行设置:bright (or bold), dimunderscoreblinkreverse,hidden, or italics

#[default] 可以重置修改后的样式。

5.3 其他配置参数

参数名称 参数含义
#H 完整主机名
#h 不含域名的主机名
#F 窗口的标记
#S session 的名字
#I window 的序号
#W 窗口的名字

此外,我们还可以通过 #(shell_cmd) 的形式运行 shell 命令来增强显示。我们还可以通过 #{VARIABLE} 的形式使用 TMUX 中的各种变量。

  1. 条件变量,例如:#{?session_attached,attached,not attached}。如果 ? 后面的变量存在并且非 0 则返回第一个变量,否则返回第二个。
  2. 变量字符串截取 #{=N:VARIABLE} 的形式获取变量的前 N 个字符, #{=-N:VARIABLE} 获取变量的后 N 个字符。
  3. 如果变量是时间戳类型的,#{t:VARIABLE} 会把时间戳转换为时间字符串。
  4. #{d:VARIABLE} 返回变量的 dirname#{d:VARIABLE} 返回 basename

更多相关配置可见于:FORMATS

6. 我的配置

以下是我的配置,部分配置还是以 2.1 为准。

# 绑定 R 重载配置文件
bind R source-file ~/.tmux.conf

# 采用 vi 模式
setw -g mode-keys vi

# 基本设置
set -g default-terminal "screen-256color"

# 设置序号从1开始
set -g base-index 1
set -g pane-base-index 1

# 关闭状态栏窗口占位的自动命名
setw -g automatic-rename off
set-option -g allow-rename off
setw -g utf8 on
set -g status-utf8 on

# 设定状态栏的位置
set -g status-position bottom

# 状态栏配置 {
    # 自动重新编号 window
    set -g renumber-windows on

    # 设置自动刷新的时间间隔
    set -g status-interval 1
    # 状态栏左对齐
    set -g status-justify left
    # 状态栏左侧宽度
    set -g status-left-length 20
    # 状态栏右侧宽度
    set -g status-right-length 50

    # 状态栏背景颜色
    set -g status-bg '#333333'
    # 状态栏前景颜色
    set -g status-fg '#ffffff'
    # 状态栏左侧显示 session 的名字
    set -g status-left '#[bg=#00bb00] [#S] #[default] '
    # 状态栏右侧显示时间
    #set -g status-right '#[fg=white,bg=#55bb00] [#h] #[fg=white,bg=#009c00] %Y-%m-%d #[fg=white,bg=#007700] %H:%M:%S '
    set -g status-right '#[fg=white,bg=#444444] [#h] #[fg=white,bg=#666666] %Y-%m-%d #[fg=white,bg=#888888] %H:%M:%S '

    # 当前激活窗口在状态栏的展位格式
    setw -g window-status-current-format '#[bg=#ff0000, fg=#ffffff, bold]*[#I] #W*'
    # 未激活每个窗口占位的格式
    setw -g window-status-format '#[bg=#0000ff, fg=#ffffff] [#I] #W '
# }

# tmux 控制相关的配置 {
    # 允许鼠标选取 Window 、Pane 以及 Pane 的大小改变,2.1 时使用如下设置
    set -g mouse on
    # 同上,1.6 时如下设置
    #set -g mouse-select-window on
    #set -g mouse-select-pane on
    #set -g mouse-resize-pane on

    # 切换为使用 Alt-方向键 切换同一 Window 中的pane
    bind -n M-Left select-pane -L
    bind -n M-Right select-pane -R
    bind -n M-Up select-pane -U
    bind -n M-Down select-pane -D
# }

每次学一个这样的高频度软件,都觉得开源世界真尼玛高深莫测,每个软件都有如此复杂的可定制性!还都是免费的!

7. 参考资料

Vagrant

1. 简介

Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统,使用 Chef创建自动化虚拟环境。

我们可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员。成员可以在自己喜欢的桌面系统(Mac/Windows/Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气。

2. 安装

2.1 安装 VirtualBox

sudo apt-get install virtualbox-5.0

2.2 安装 Vagrant

下载地址:http://downloads.vagrantup.com/ 根据提示一步步安装。

sudo apt-get install vagrant

2.3 下载官方封装好的基础镜像:

如果你要其他系统的镜像,可以来这里下载

3. 相关操作

3.1 添加镜像

如果下载镜像的存放路径为 ~/path/to/image.box,那么添加 box 的方法为:

vagrant box add <BOX_NAME> ~/path/to/image.box

3.2 初始化开发环境

cd ~/path/to/dev_dir
vagrant init <BOX_NAME> #切换目录
vagrant up #初始化

接着配置环境参数。

vagrant ssh
cd /vagrant

~/path/to/dev_dir 目录对应虚拟机中的 /vagrant

3.3 其他设置

Vagrant 初始化成功后,会在初始化的目录里生成一个 Vagrantfile 的配置文件,可以修改配置文件进行个性化的定制。

Vagrant 默认是使用端口映射方式将虚拟机的端口映射本地从而实现类似 http://localhost:80 这种访问方式。这种方式比较麻烦,新开和修改端口的时候都得编辑。相比较而言,host-only 模式显得方便多了。打开 Vagrantfile,将下面这行的注释去掉(移除#)并保存:

config.vm.network :private_network, ip: "192.168.33.10"

重启虚拟机,这样我们就能用 192.168.33.10 访问这台机器了,你可以把 IP 改成其他地址,只要不产生冲突就行。

3.4 打包

vagrant package

4. 常用命令

vagrant init  # 初始化 
vagrant up  # 启动虚拟机 
vagrant halt  # 关闭虚拟机 
vagrant reload  # 重启虚拟机 
vagrant ssh  # SSH 至虚拟机 
vagrant status  # 查看虚拟机运行状态 
vagrant destroy  # 销毁当前虚拟机

5. 注意事项

使用 Apache/Nginx 时会出现诸如图片修改后但页面刷新仍然是旧文件的情况,是由于静态文件缓存造成的。需要对虚拟机里的 Apache/Nginx 配置文件进行修改:

# Apache 配置添加: 
EnableSendfile off 
# Nginx 配置添加: 
sendfile off;

参考文章

使用 Vagrant 打造跨平台开发环境

一个跨平台的离线文档浏览器——Zeal

引言

对于一个程序员来说,查阅编程语言或者框架的手册是家常便饭,但是频繁打开浏览器总是一件很麻烦的事情。

之前在学 Ruby on Rails 时看到了 MacBook 上的 Dash,用起来真方便!可惜也只是 MacBook 上的,我等穷鬼只能羡慕。

小小搜索了一下,在 Github 上发现了一个名为 Zeal 的项目。

Zeal

这个软件的有以下几个特点:

  1. 跨平台。Windows 和 Linux 下都有对应版本。
  2. 支持众多的框架和语言。听过的没听过的都能在这里找到,还可以定制自己的语言手册。
  3. 与集成开发环境和文本编辑器集成。
  4. 支持搜索。

放一张图片:
示例图

更多资料