Ngrok如果你完全不知道它是什么东西,可以在它的github项目上了解下:https://github.com/inconshreveable/ngrok

简单概括:能够将你本机的HTTP服务或TCP服务,通过部署有ngrok服务的外网伺服器暴露给外网访问,网上所说的内网穿透

之前的几个月里本人一直用官方订阅版本的ngrok,之所以用付费模式,主要因为免费模式每次都生成一个随机的二级域名,让人很不舒服,但实际几个月下来的使用情况,评估发现总体用的频率并不是很高,同时网络效果也不是很好(应该和墙有关),同时也尝试了一下国内小米球Ngrok,同样有一些不稳定因素,所以打算自己编译一个私有的Ngrok,在编译过程中发现了不少问题,重新整理一遍文档。

1. 安装go语言开发环境/Git

ngrok是利用go语言开发的,所以先要在服务器上安装go语言开发环境。

yum install golang

~/.bash_profile文件内,加入以下环境变量配置内容:

export GOPATH=$HOME/go
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$GOPATH/bin

最后保证可通过go env查看是否配置成功。

安装Git方式略过,这里没有对版本有要求,我们只是利用GIt获取Ngrok源码,不用Git直接Wget github zip文件也是可以的。

3. 获取ngrok的源码

由于下面编译过程需要改官方的部分源码,同时这里也测试过官方最新的版本总是存在「remote error: bad certificate」问题(文末有描述)。这里用的是mamboer的源码基于1.7.1版本,应该有做一些变更,所以尽可能Fork一份源码至自己的Github账户。

cd /usr/local
git clone https://github.com/mamboer/ngrok.git

源码拉取下来后,看情况需要修改一个地方: 打开 src/ngrok/log/logger.go 文件 将 code.google.com/p/log4go 修改为 github.com/alecthomas/log4go 这里主要考虑 code.google.com 已经下线,其实不修改也可以。

4. 生成自签名证书

使用ngrok.com官方服务时,我们使用的是官方的SSL证书。

自建ngrokd服务,证书这里也可以用Godaddy付费证书/Let’ Encrypt免费证书,不过出于个人测试或者沙盒的要求,就不用第三方证书。所以我们需要生成自己的自签名证书,并编译一个携带该证书的ngrok客户端。

证书生成过程需要一个「基础域名」。 以ngrok官方随机生成的地址”1iedks2cv.ngrok.com”为例,其「基础域名」就是”ngrok.com”,如果你要 提供服务的地址为”example.ngrok.xxx.com”,那「基础域名」就应该 是”ngrok.xxx.com”。

我们这里以「基础域名」=”ngrok.crackedzone.com”为例,因为我将来希望建立”pay.ngrok.crackedzone.com”用于平台支付回调的穿透模式。

在此之前我们给域名”crackedzone.com”添加两条A记录:”ngrok.crackedzone.com”和”*.ngrok.crackedzone.com”,指向这台Ngrok所在的服务器ip。

同时在服务器上生成证书的命令如下:

cd ngrok
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=ngrok.crackedzone.com" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=ngrok.crackedzone.com" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

执行完以上命令,在ngrok目录下就会新生成6个文件:

-rw-rw-r-- 1 lv lv  985 Feb 24 19:04 device.crt
-rw-rw-r-- 1 lv lv  895 Feb 24 19:04 device.csr
-rw-rw-r-- 1 lv lv 1679 Feb 24 19:03 device.key
-rw-rw-r-- 1 lv lv 1675 Feb 24 19:01 rootCA.key
-rw-rw-r-- 1 lv lv 1103 Feb 24 19:03 rootCA.pem
-rw-rw-r-- 1 lv lv   17 Feb 24 19:04 rootCA.srl

ngrok 编译过程会加载 assets/client/tls, assets/server/tls 这里的证书资源文件,替换成自己生成的。

rm -f assets/client/tls/ngrokroot.crt
rm -f assets/server/tls/snakeoil.crt
rm -f assets/server/tls/snakeoil.key

cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key

5. 编译客户端ngrok和服务端ngrokd

make release-server release-client

成功编译后,会在bin目录下找到ngrokd和ngrok这两个文件。

ngrok可以下载到内网的Client服务器上,存放在/usr/local/bin/ngrok

6. 服务端运行ngrokd服务

nohup /usr/local/ngrok/bin/ngrokd -domain="ngrok.crackedzone.com" -httpAddr=":80" > /tmp/ngrok.log 2>&1 &

有需要可以编写一个服务文件,同时记得开放防火墙80端口和4443端,如果证书需要包括443端口。

7. 客户端运行ngrok

创建一个配置文件: ngrok.yml

server_addr: "ngrok.crackedzone.com:4443"
trust_host_root_certs: false

tunnels:
  pay:
    remote_port: 80
    subdomain: pay
    proto:
      http: 127.0.0.1:10780

启动客户端

/usr/local/bin/ngrok -config=/root/ngrok.yml start pay

注意事项

客户端”ngrok.yml”中”server_addr”后的值必须严格与服务端-domain以及证书中的「基础域名」相同,否则Server端就会出现如下错误日志:

[02/24/20 09:55:46] [INFO] [tun:15dd7522] New connection from 27.12.33.23:3994
[02/24/20 09:55:46] [DEBG] [tun:15dd7522] Waiting to read message
[02/24/20 09:55:46] [WARN] [tun:15dd7522] Failed to read message: remote error: bad certificate
[02/24/20 09:55:46] [DEBG] [tun:15dd7522] Closing

头一次接触ORID方法在2015年的一次敏捷回顾上,但是还不知道它,当天围坐在小会议室中通过该方法总结迭代开发经验,使我很有收获。

ORID工作法很好理解,几乎一听就会,只是日常工作中我们总会选择更偷懒的方法,而忽略了总结过程中思考和逻辑的重要性。根据百度百科,ORID是一种通过催化师引导来开展的结构化汇谈(会议、交谈)形式。该方法常被用作对事实进行分析和感觉某一工具和方法。

通过这个方法,在两年后我自己主导转型敏捷迭代开发中再次利用到,可以设计引导结构:

  • Objective: 上个迭代有哪些让你印象深刻的事情发生?你看到了什么?
  • Reflective:哪些场景让你兴奋?哪些地方不那么顺利?
  • Interpretive:为什么会不顺利?这些数据使你意识到了什么?我们如何才能做得更好?
  • Decisional:什么是下个迭代我们可以立刻开始动手的?

此次通过该引导,我得到这样的结论:

回顾

Objective

  1. 团队很和谐,研发节奏很好。
  2. 项目每到上线发布时刻,很紧急。
  3. 便利贴对工作帮助很大。
  4. 对功能细节的评审缺乏。
  5. 产品有太多的优化空间。

Reflective

  1. 工作交流比较开心。
  2. 虽然加班,但是也很有劲。
  3. 看到产品没有人使用,不开心。
  4. 看不到决策层反馈,比较迷茫。

Interpretive

  1. 每天的计划可以做的更细致。
  2. 研发过程中还是需要多沟通。
  3. 定期的传达决策层的建议。
  4. 需要有更好的用户体验。
  5. 团队需要保持。
  6. 需要团建。

Decisional

  1. 希望研发团队能有经费做一次聚餐
  2. 希望看到领导层面对这个项目的期望以及信息的传达
  3. 希望针对这个项目招聘一个推广运营
  4. 每一个研发迭代需求文档提早一个迭代期出来
  5. 每个便利贴都有一个负责人标示在便利贴上
  6. 尽量在周二上午就提交这个一个迭代的功能验收测试版本
  7. 每天站会细致的定义今天的工作必须完成的内容
  8. 迭代的需求评审会议议定要订出本次迭代的功能目标

将Decisional作为下一个迭代要去执行的工作,如此看来相当有难度,说明我的团队管理还是做得不够。

1. 启动网卡

ifup eth0

2. SSH链接 ifconfig 查看IP后SSH终端连接

3. 更新基本软件包

yum install ntpdate wget lsof -y 

备份原系统更新源

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

进入yum.repos.d目录

cd /etc/yum.repos.d
# 下载网易镜像源:
wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
# 或者
# 下载搜狐镜像源:
wget http://mirrors.sohu.com/help/CentOS-Base-sohu.repo

更新系统以及内核

yum clean all
yum makecache
yum upgrade

4. 系统时间更新和设定定时任务

echo '*/30 *  *  *  *  /usr/sbin/ntpdate cn.pool.ntp.org && hwclock -w && hwclock --systohc >/dev/null 2>&1' >> /var/spool/cron/root

5. 修改ip地址、网关、主机名、DNS #eth0 网卡设置

mv /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.bak
vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 #网卡设备名称
HWADDR=00:0C:29:D0:C7:B5 #以太网设备的对应的物理地址
TYPE=Ethernet #网络类型为以太网模式
UUID=080a457b-6a53-4a3a-9155-a23c1146c2c6 #通用唯一识别码
ONBOOT=yes #是否启动引导的时候激活YES
NM_CONTROLLED=no #设备eth0是否可以由Network Manager图形管理工具托管
BOOTPROTO=dhcp #静态IP地址获取状态 如:DHCP表示自动获取IP地址
IPADDR=192.168.1.10 #IP
IPV6INIT=no
IPV6_AUTOCONF=no
NETMASK=255.255.255.0 #网卡对应的网络掩码
GATEWAY=192.168.1.1 #网关地址

网关配置

vi /etc/sysconfig/network
#表示系统是否使用网络,一般设置为yes。如果设为no,则不能使用网络,而且很多系统服务程序将无法启动
NETWORKING=yes
#设置本机的主机名,这里设置的主机名要和/etc/hosts中设置的主机名对应
HOSTNAME=c65mini.localdomain
#设置本机连接的网关的IP地址。例如,网关为10.0.0.1或者192.168.1.1
GATEWAY=192.168.1.1

DNS

vi /etc/resolv.conf
; generated by /sbin/dhclient-script
nameserver 8.8.8.8
nameserver 4.4.4.4

HOSTS

vi /etc/hosts
127.0.0.1 lvtao.localdomain
#使用DNS域名服务器来解析名字
order bind hosts
#一台主机是否存在多个IP
multi on
#如果用逆向解析找出与指定的地址匹配的主机名,对返回的地址进行解析以确认它确实与您查询的地址相配。为了防止“骗取”IP地址
nospoof on

重启网卡

service network restart

6. 修改SSH端口号和屏蔽root账号远程登陆

#备份SSH配置 
cp /etc/ssh/sshd_config sshd_config_bak 
#修改SSH安全配置 
vi /etc/ssh/sshd_config
#SSH链接默认端口
port 52113
#禁止root账号登陆
PermitRootLogin no
#禁止空密码
PermitEmptyPasswords no
#不使用DNS
UseDNS no

重启服务确认端口生效

/etc/init.d/sshd reload 
lsof -i tcp:52113

7. 锁定关键文件系统

chattr +i /etc/passwd
chattr +i /etc/inittab
chattr +i /etc/group
chattr +i /etc/shadow
chattr +i /etc/gshadow

8. 精简开机自启动服务

#关闭全部服务
for sun in `chkconfig --list|grep 3:on|awk '{print $1}'`;do chkconfig --level 3 $sun off;done
#开启需要的服务
for sun in crond rsyslog sshd network;do chkconfig --level 3 $sun on;done
#或者需要使用防火墙的话可以开启iptables和ip6tables
for sun in crond rsyslog sshd network iptables ip6tables;do chkconfig --level 3 $sun on;done
> chkconfig --list|grep 3:on
crond           0:off   1:off   2:on    3:on    4:on    5:on    6:off
ip6tables       0:off   1:off   2:on    3:on    4:on    5:on    6:off
iptables        0:off   1:off   2:on    3:on    4:on    5:on    6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off
rsyslog         0:off   1:off   2:on    3:on    4:on    5:on    6:off
sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off

9. 调整文件描述符大小

设置配置,重启生效

echo '* soft nofile 65535 
* hard nofile 65535 
* soft nproc 65535 
* hard nproc 65535 
* soft nofile 65535
* hard nofile 65535' >> /etc/security/limits.conf 

临时生效

ulimit -SHn 65535
ulimit -s 65535

10. 设置系统字符集,使用英文

sed -i 's#LANG="zh_CN.*"#LANG="en_US.UTF-8"#' /etc/sysconfig/i18n

11. 内核参数优化 vi /etc/sysctl.conf

mv /etc/sysctl.conf /etc/sysctl.conf.default
echo 'net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768

net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

net.ipv4.tcp_tw_recycle = 1
#net.ipv4.tcp_tw_len = 1
net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800

#net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024 65535

net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120' > /etc/sysctl.conf

### 生效
sysctl -p

12. 删除不必要的系统用户和群组

#删除不必要的用户
userdel adm
userdel lp
userdel sync
userdel shutdown
userdel halt
userdel news
userdel uucp
userdel operator
userdel games
userdel gopher
userdel ftp
#删除不必要的群组
groupdel adm
groupdel lp
groupdel news
groupdel uucp
groupdel games
groupdel dip
groupdel pppusers

13. 设置一些全局变量

#设置自动退出终端,防止非法关闭ssh客户端造成登录进程过多,可以设置大一些,单位为秒
echo "TMOUT=3600">> /etc/profile
#历史命令记录数量设置为10条
sed -i "s/HISTSIZE=1000/HISTSIZE=10/" /etc/profile
#立即生效
source /etc/profile

由于公司搬迁到原因,一直以来都和其他部门公用SVN,权限分配也是分管部门配置的,SVN上很多项目文件,各种branches,tags命名不规范化,产品运营也都混合使用,介于此情况下,考虑将我们有价值以及正在研发都项目都迁移到我们自己到Git服务上,综合考虑决定搭建一个GitLab。

部署GitLab

部署本身很简单,官方有简单到安装命令步骤

yum install curl policycoreutils openssh-server openssh-clients
yum install postfix
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
yum install gitlab-ce
yum install lokkit
lokkit -s http -s ssh

安装完先打开 /etc/gitlab/gitlab.rb 修改几个简单到配置,域名/备份路径/仓库路径(保证有充足到磁盘空间)

external_url 'http://gitlab.mydomain.com'
gitlab_rails['backup_path'] = "/home/git/backups"
git_data_dirs({"default" => { "path" => "/home/git" }})

初始化配置

gitlab-ctl reconfigure

重启GitLab服务

gitlab-ctl restart

设置Crontab备份操作

  0  2  *  *  * /usr/bin/gitlab-rake gitlab:backup:create

之后访问平台WEB操作,重置管理员密码,创建用户,组,项目信息

一切就绪,我们需要开始导入原来SVN上需要到项目,这里需要操作时支持git svn命令

迁移

建立users.txt(存储svn账号与gitlab上账号的关联性)

格式: svn用户名 = git用户名,如:

yonghe = yonghe<×××@163.com>  
lihe = lihe<×××@163.com>  

注意: svn里面有的账号必须要做关联,否则clone会失败。比如上面的user11找不到是哪个开发人员,也不知道它该对应哪个git账号,那就随便指定一个git账号就行了,这样做的目的其实就是将user11在svn里面的所有提交日志关联到yqdong的git账号下。转到git之后,原svn账号就无关紧要,各司其职了。

绑定 users.txt 的意义仅在于,将svn里面的提交者日志,注意是提交者,不是svn里面所有的用户信息都得关联,仅仅是往项目提交过代码的svn账号,将这些svn账号找出来,然后关联到现有的git账号,一旦转到git上之后,每个git用户就能看到自己过去在svn里面提交的日志,绕了这么大一圈,现在明白了吧?

可以通过以下命令快速创建 users.txt

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

导出svn上到项目数据

git svn clone https://svn.mydomain/amz/selenium-center/ --trunk="trunk" --tags="tags" --branches="branches" --authors-file=amz-selenium-center/users.txt --no-metadata selenium-center

添加GitLab到Git源信息

git remote add origin [email protected]:amz/selenium-server.git

将trunk, branches等上传

git push origin master

回到GitLab平台既可看到项目相关Commit信息

更多参考文档:实际操作 Svn 迁移到 Git

开发机一直使用brew来安装PHP及其他的环境,今天把PHP升到7.1,由于7.1版本下还没有runkit的源,官方也没有更新支持到php7,庆幸Github上有人Fork后做了支持,所以无法使用brew安装,只能编译安装了。

首先下载runkit,解压,进入目录。

只好从 Nginx 上想其他的方案,毕竟之前曾利用 lua 脚本对 MySQL 连接请求进行改造过,果不其然,有类似的模块可以拷贝一个请求。

git clone https://github.com/runkit7/runkit7
cd runkit7
$(brew --prefix homebrew/php/php71)/bin/phpize
./configure --with-php-config=$(brew --prefix homebrew/php/php71)/bin/php-config
make && make install
make test

$(brew –prefix homebrew/php/php71) 即 brew info php71结果中的path值。

由于brew安装PHP会在php.ini同级目录创建conf.d目录,并把扩展的配置文件写在这里,一目了然知道都安装了哪些扩展,所以也以同样方式在此目录创建ext-runkit.ini。

make install 后会显示,具体路径可能会不一样。

Installing shared extensions:  /usr/local/Cellar/php71/7.1.0_11/lib/php/extensions/no-debug-non-zts-20160303/

这个目录即扩展.so的存放目录。下边会用到。

[runkit]
extension="/usr/local/Cellar/php71/7.1.0_11/lib/php/extensions/no-debug-non-zts-20160303/runkit.so"

至此,重启php-fpm就可以了。