使用nosql缓存session数据

场景需求

使用PHP搭建网站或API Server时,常常需要用到$_SESSION['user']等全局变量获取到用户的状态及数据。若服务器已经安装memcached/redis,则可通过相关的配置,将session文件缓存到memacached/redis服务器,降低硬盘IO,提升网站的性能。

配置nosql缓存Session

可以通过命令行配置,修改php.ini,将session.save_handler修改为memcached/redis,同时,将原有的/tmp路径更改为服务器memcached服务的ip及端口。

1
2
session.save_handler = memcached
session.save_path = "127.0.0.1:11211"

还可以通过session.gc_maxlifetime配置缓存的时间。

1
session.gc_maxlifetime = 1440

也可直接使用Redis储存Session数据,

1
2
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

多服务器

当我们的服务使用一台服务器已经无法满足的时候,并开始集群化部署,同一个用户可能会访问到不同服务器,这时候就需要多服务器共享session,虽然使用一台memcached也足以应付,但若需要使用memcached集群,则可进一步配置。
可以使用,将服务器集群隔开,并使用不同额参数来配置各个memcached服务器的比重等等,可参考Memcached::addServer

1
session.save_path = "127.0.0.1:11211?weight=67,127.0.0.2:11211?weight=33"

SASL认证

一方面,若使用第三方的服务,则需要账号密码鉴权,另一方面,服务器较多或出于安全性考虑,也可以在php.ini中配置帐号密码。

1
2
3
4
5
6
[memcached]
memcached.use_sasl = On
memcached.sess_binary = On
memcached.sess_sasl_username = “your_ocs_name”
memcached.sess_sasl_password = “your_ocs_password”
memcached.sess_locking = Off

解决跨域问题

对于大型的BS网站,通常按不同服务器运行不同功能模块及子系统,分别使用不同的域名或者同样的域名,比如yatesun.comwww.yatesun.com等等。默认的情形下,客户端访问不同服务器或同一台服务器的不同hosts(domain),服务器会为不同的客户端生成不同的SESSION_ID,用于识别每一位用户。对于同一个客户端,SESSION_ID在有效期内是不会变的。对于不同的服务器,通过使用Memcached已经解决了Session的保存问题。那么对于不同域名之间的跨域,同样可以在php.ini的配置中进行配置,
解决跨域问题

1
session.cookie_domain = ".yatesun.com"

或针对每个应用进行独立配置,

1
ini_set('session.cookie_domain', '.yatesun.com');

配置成功后,*.yatesun.comyatesun.com就均可访问此cookie,并通过memcached集群获取到SESSION_ID对应的用户数据,基本解决跨域问题。

可能存在的问题

由于Memcached使用LRU(Least Recently Used)算法回收缓存,LRU算法是针对每个slab类执行,而不是针对整个Memcached,核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。最近最少使用的数据有可能被回收,这意味着有可能用户在某个时间点登录了,但又长期不在线,隔了较长一段时间之后,可能他的session已经被回收了。
当然这仅仅是一种可能性,若从可靠性来讲,使用Redis将是一种更好的选择。
可参考Memcached作者两篇文章Sessions in MemcachedCache your sessions,还有一篇Memcached的流程图

更多配置

更多的配置还可以参考Memcached运行时配置

PHP框架Laravel 5.2笔记

前言

Laravel其实也刚发布不久,以前我一直喜欢使用原生php,一直追求极致,希望能有更高的效率,原始php代码显然效率是最高的。随着php升级到php7后,性能似乎不是一个特别必须的要求。本着多学点知识的前提,开始学习Laravel,科技产品用新不用旧,当然要选择最新版来实施这个研究。
新的5.2版本加入了中间件组、MySQL JSON、表单数组校验、增强数据库Session驱动、集合通配符、认证视图及隐形模型绑定等功能。
Laravel也是使用了PDO连接数据库,这我挺喜欢的。

服务器环境

软件 版本 软件 版本
Linux CentOS 7.1 php 7.0.6
mysql 5.5 nginx 1.10.0

安装Composer

Composer算是一个安装工具,通过它可以优化代码的部署流程。这也是安装Laravel的前提条件之一。

1
2
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

配置php环境参数

在执行安装的过程中,我所用的服务器有如下的报错:

1
/usr/bin/env: php: No such file or directory

研究后,我发现是没有配置好php的环境,执行下面的命令即可:

1
export PATH=$PATH:/usr/local/php/bin

安装Laravel

发现Laravel所生成的路径与Node.JS有很多相似之处,都是默认通过/public/访问主目录。有些类似hexo的生成方式。
执行如下命令,安装Laravel:

1
composer global require "laravel/installer"

至此,可以通过/root/.composer/vendor/bin/laravel执行laravel所支持的简单命令。

创建新应用

生成应用目录也很简单,仅需一行命令即可。

1
/root/.composer/vendor/bin/laravel new laravel

然后laravel/public/就是laravel的主目录了。
在此之前,还需要在php.ini文件中,取消禁用下面的两个函数(功能),才能顺利安装:

1
2
proc_get_status()
proc_open

500错误

因为laravel/storage目录没有777权限。

1
sudo chmod -R 777 storage

nginx配置

增加文件laravel.conf,内容如下:

1
2
3
4
try_files $uri $uri/ @rewrite;
location @rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}

并在相应的nginx配置文件中,增加一行include laravel.conf,执行service nginx reload即可使其生效。

HTTP路由

编辑路由文件,可以简单修改路由规则,vim app/Http/routes.php,可以注册路由来响应任何HTTP请求:

1
2
3
4
5
6
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
Route::get('/', function () {
return view('welcome');
});
Route::get('about', function () {
return view('app');
});
Route::get('site/about', function () {
return view('site.hello');
});
Route::get('errors', function () {
return view('errors.503');
});
Route::get('site', 'SiteController@index');

请求/时,返回welcome页面;
请求/about时,返回app页面;
请求site/about时,返回site/hello页面;
请求site时,交给控制器SiteController的index方法来处理。

输出变量

在php中,我们可以使用<?=$name?>来输出一个变量的值,但在laravel中,定义了一种新的方法。

1
2
{{$name}}
{!!$name!!}

区别在于,前者会将html的符号转制,后者将直接输出html代码。当我们希望将源码显示出来的时候,应当使用前者。当我们希望能够修改html页面的样式并实现相应的效果,或执行一些命令的时候,就可以使用后者。
不应当直接在模板中使用{!!$something!!}等标签,因为当这些变量不存在的时候,页面可能会报错,如果你希望他可以为空,可以使用Blade模板,也可以使用if语句判断。

Blade模板

在网站开发过程中,引入的css等等可能每个页面都是一样的,这时候就能发挥Blade模板的作用了。
新建模板页面,在页面中所需要填充的位置加入,如:@yield('content')@yield('title')
当另一个页面需要引用这个Blade模板时,新建一个blade页面,

1
2
3
4
5
6
7
@extends('app')
@section('title')
标题 {{$name}}
@stop
@section('content')
{{$hello}} - {!!$hello!!}
@stop

判断与循环语句

laravel代码中支持一些if和foreach语句,如:

1
2
3
4
5
6
7
8
9
@if($name == 'YateSun')
doing A
@else
doing B
@endif

@foreach($group as id => $user)
doing C
@endforeach

创建Model

1
php artisan make:model Test

创建控制器

1
php artisan make:controller SiteController

使用命令行工具

1
php artisan tinker

通过shell命令行,可以进入laravel的命令行交互界面;

1
2
3
4
$test = new App\Test
$test->title="My first Title";
$test->published=Carbon\Carbon::now();
$test->save();

Session

落地保存

需要主动在调用完controller之后,调用了session->save()的方法,来主动的保存session。这样session才能落地保存起来,如果在controller或者view里面写了exit;die();,那么session是不会被保存的,除非主动的写Session::save()才能手工的保存起来。

1
$request->session()->save();

flash

经过flash所存储的值,本次请求可以使用,二次http请求也可以使用,使用完自动销毁,第三次就不存在了。

增加Redis支持

1
2
3
4
5
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"predis/predis": "~1.1@dev"
},

nginx的优化、反向代理及各个模块配置

nginx是什么

Nginx(engine x)是一个网页服务器,它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的协议链接,以及一个负载均衡器和一个HTTP缓存。
起初主要供俄国大型的门户网站及搜索引擎Rambler使用,因此同样的服务器配置下,nginx会比apache有着更优的性能、更高的并发量。目前各大企业,包括腾讯、京东、淘宝在内均已开始使用nginx作为web服务器。

HTTP基本认证模块

当我们有了一些静态文件或者静态页面,但是又不想使用一些动态脚本来控制他们的的访问权限,毕竟动态脚本会影响到访问速度,这时候便可以仅仅依靠nginx来完成http的基本认证。
需在nginx的配置文件中加入如下配置来达到控制权限的目的,可以指定到某个目录,也可以进行一些正则匹配,也可以直接整个域名控制权限。

1
2
auth_basic "secret";
auth_basic_user_file /path/to/passwd.db;

在这之前,还需设置可登录的用户名及密码,这时候需要用到htpasswd这个工具,另外也可以使用openssl,本文使用htpasswd生成用户名密码文件。

1
htpasswd -c passwd.db yms

然后输入密码,再次确认密码。
执行以下命令平滑重启nginx服务:

1
service nginx reload

登录你的网站,这时候会返回405错误,并且提示你需要输入帐号及密码才可访问。

反向代理

只需要配置好路径,及对应的反向代理路径即可,如下面命令所示:

1
2
3
4
location ^~ /api
{
proxy_pass http://192.168.0.1;
}

nginx解决跨域问题

部分图片可能跨域无法访问,因此需要在图片服务器进行配置,对图片目录增加允许跨域:

1
add_header Access-Control-Allow-Origin *;

nginx负载均衡

1
2
3
4
5
upstream phpserver {
server 192.168.0.77:3000 weight=2;
server 192.168.0.66:80 weight=2;
}
proxy_cache_path /var/cache/nginx/nginx_cache levels=1:2 keys_zone=first:300m inactive=1h max_size=5g;
1
2
3
4
5
6
7
8
9
10
11
12
13
add_header X_Cache "$upstream_cache_status from $server_addr";
location / {
proxy_pass http://phpserver;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($request_method = "POST") {
proxy_pass http://10.10.0.1;
}
if ($request_method = "PUT") {
proxy_pass http://10.10.0.2;
}
}

Redmine项目管理的安装及配置

Redmine是什么

Redmine 是一个网页界面的项目管理与缺陷跟踪管理系统的自由及开放源代码软件工具。它集成了项目管理所需的各项功能:日历、燃尽图和甘特图以协助可视化表现项目与时间限制,问题跟踪和版本控制。此外,Redmine也可以同时处理多个项目。
Redmine是以Ruby on Rails撰写的架构,它横跨多个平台与数据库,它的设计很明显是受一些类似功能软件包的Trac所影响。

安装过程

Redmine对我来说,是一个特别陌生的工具,之前也没有使用过的经历,但是因为单位项目管理的需求,需要安装一下这个软件。几个同事也试过,但是总会因为这些那些的原因,导致还是没能顺利安装。其实网上有特别多的教程,但是几乎没有一个能用的,我在安装过程中也遇到特别多的困难,但是最终却发现其实官网的教程反而是最可靠的,于是顺利安装,有了下面这个教程。

下载安装包

目前最新的包是redmine-3.2.1.tar.gz

设置数据库

我使用的是mysql,因此需要建立相应数据库、redmine用户、设置访问权限:

1
2
3
REATE DATABASE redmine CHARACTER SET utf8;
CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'my_password';
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';

还需要配置相应的数据库配置文件,先解压安装包:

1
2
3
4
tar zxf redmine-3.2.1
cd redmine-3.2.1/config/
mv database.yml.example database.yml
vim database.yml

修改如下的配置:

1
2
3
4
5
6
production:
adapter: mysql2
database: redmine
host: localhost
username: redmine
password: my_password

安装Ruby环境及Gem

安装Redmine需要用到Ruby和Gem,

1
2
3
curl -L https://get.rvm.io | bash
source /etc/profile.d/rvm.sh
rvm install 2.3.0

配置环境

这里需要使用到Bundler来安装,执行一下命令:

1
2
gem install bundler
bundle install --without development test rmagick

在安装过程中如果报错,或缺失某些包,可编辑Gemfile,修改第一行为淘宝源:

1
source 'https://ruby.taobao.org'

配置rake

在执行redmine服务的时候,需要用到该服务,执行以下命令,生成一些必须文件:

1
bundle exec rake generate_secret_token

创建数据库初始信息

1
RAILS_ENV=production bundle exec rake db:migrate

默认数据库设置

1
RAILS_ENV=production bundle exec rake redmine:load_default_data

设置文件系统权限

1
2
3
mkdir -p tmp tmp/pdf public/plugin_assets
sudo chown -R redmine:redmine files log tmp public/plugin_assets
sudo chmod -R 755 files log tmp public/plugin_assets

试运行

执行下面一行命令可以将redmine运行在http://localhost:3000

1
bundle exec rails server webrick -e production

初始redmine帐号为admin,密码也是admin,如果测试成功,那么到这里就成功安装了该软件。

正式环境配置

正式环境需要将webrick在后台运行,并且可能还需要监听0.0.0.0,而不是127.0.0.1,因此可能还需要用到如下的命令,并将其加入到开机执行脚本中,这样将每次开机时自动开启。

1
cd /path/to/redmine-3.2.1/ && bundle exec rails server -b 0.0.0.0 webrick -e production -d

配置邮箱通知服务

修改config/configuration.yml文件,加入如下配置:

1
2
3
4
5
6
7
8
9
10
default:
email_delivery:
delivery_method: :smtp
smtp_settings:
address: "smtp.yourdomain.com"
port: 25
authentication: :login
domain: 'yourdomain.com'
user_name: 'username@yourdoain.com'
password: 'yourpassword'

至此,redmine服务配置就完成了,接下来只需要登录http://ip:3000,在界面上根据步骤配置即可。

使用Let's Encrypt自动生成HTTPS证书

Let’s Encrypt是什么

Let’s Encrypt是一个免费、开放、可自动化部署的证书签发服务,申请该证书完全免费,只需要验证域名的所有权。一开始我并不打算了解这个服务,但后来发现它能够支持ECC证书。继而有了研究的兴趣,过程中遇到了许多困难,但最终还是搞定了,总结出一些简单粗暴的方法。
同RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)也属于公开密钥算法。
ECC算法与RSA算法最大的不同就是,ECC的密钥长度远比RSA短。256位的ECC密钥长度,却是2048位RSA密钥长度的十二分之一,也能实现与RSA同等的加密强度,且ECC算法加解密速度更快,存储空间占用更小,带宽要求更低,更适用于移动互联网环境。本网站使用了长度为384位ECC密钥,这是目前LE服务支持的最高级别的ECC证书了。本文参考了GitHub上的文档。

安装le.sh

1
2
curl https://get.acme.sh | sh
alias acme.sh=~/.acme.sh/acme.sh

安装完成之后,这些脚本会在~/.acme.sh/目录下,用于执行命令的脚本是~/.acme.sh/acme.sh

签发证书

1
acme.sh issue /data/hexo/public/ yatesun.com www.yatesun.com,blog.yatesun.com ec-384 && cd /root/.acme.sh/ &&cat yatesun.com/yatesun.com.cer yatesun.com/yatesun.com.csr yatesun.com/ca.cer >yatesun.com/yatesun.com.crt && lnmp nginx reload

通过该命令,可以签发得到包含100个域名在内的HTTPS证书,需通过cat将三个不同的文件合并之后,nginx才可以直接使用。

nginx配置

加入如下命令,因为Let’s Encrypt需要指定根目录,它会加入一些验证文件到.well-known/acme-challenge/目录,也选择其他方式让该路径可访问。

1
2
3
location ~ /\.well-known
{
}

配置自动部署

/etc/crontab中加入如下脚本:

1
0 0 1 * * root acme.sh issue /data/hexo/public/ yatesun.com www.yatesun.com,blog.yatesun.com ec-384 && cd /root/.acme.sh/ &&cat yatesun.com/yatesun.com.cer yatesun.com/yatesun.com.csr yatesun.com/ca.cer >yatesun.com/yatesun.com.crt && lnmp nginx reload

至此,HTTPS证书将会在每个月1号自动更新,另外写一个脚本重启一下nginx即可。

搭建ElasticSearch本地搜索引擎

当前网站使用的是Google搜索,通过表单的形式提交搜索内容+site:yatesun.com,从而达到站内搜索的目的。但Google未必是所有访客都能访问到,因此我也希望能够自己建立一套独立可行的搜索功能,着手开始研究基于Lucene的ElasticSearch,希望能以此打造一个真正的站内搜索。

一、安装 ElasticSearch

需要先安装Java环境,安装前可能我们并不知道最新的java版本,可以用以下命令查找。

1
yum list java*

java-1.8.0-openjdk-headless.x86_64正是将要用到的。

1
yum install java-1.8.0-openjdk-headless.x86_64

检查当前最新版本
由于IK分词暂时不支持2.2.0,所以我还是选择了2.1.1,没有使用最新版本。
我选择了最新版的2.3.1版,分词器选择1.9.1版。
由于无法使用root用户直接运行,在使用root的情况下,可以按以下命令下载、执行,我添加了用户elasticsearch专门用来运行ElasticSearch。

1
2
3
4
5
6
7
8
adduser elasticsearch
cd /home/elasticsearch/
wget -c https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.2/elasticsearch-2.3.2.tar.gz
tar -zxf elasticsearch-2.3.2.tar.gz
mv elasticsearch-2.3.2 es
chown elasticsearch:elasticsearch es -R
su - elasticsearch -c "chmod a+x es/bin/elasticsearch"
su - elasticsearch -c "./es/bin/elasticsearch"

另行启动一个shell,用curl验证服务开启情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -XGET http://127.0.0.1:9200/?pretty

{
"name" : "Eon",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.3.2",
"build_hash" : "b9e4a6acad4008027e4038f6abed7f7dba346f94",
"build_timestamp" : "2016-04-21T16:03:47Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}

可修改config/elasticsearch.yml,加入

1
2
network.bind_host: "0.0.0.0"
network.publish_host: _non_loopback:ipv4_

二、安装 IK Analysis

一般的搜索,都需要有一个方便易用的分词器,默认的分词似乎还不能满足需求,因此,根据作者的建议,我也使用了elasticsearch-analysis-ik作为分词插件。

安装maven

下载maven最新版本

1
2
3
4
wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
tar -zxf apache-maven-3.3.9-bin.tar.gz
ln -s apache-maven-3.3.9 apache-maven
vim /etc/profile

加入如下文字:

1
2
3
export M2_HOME=/home/elasticsearch/apache-maven
PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
export PATH

执行mvn -V检验是否安装成功。

安装分词器

1
2
3
4
5
6
7
8
9
10
11
12
13
wget -c https://codeload.github.com/medcl/elasticsearch-analysis-ik/zip/master
unzip unzip master
cd elasticsearch-analysis-ik-master
yum install maven
mvn package
cd target/releases/
mkdir /home/elasticsearch/es/plugins/ik
mv elasticsearch-analysis-ik-1.9.2.zip /home/elasticsearch/es/plugins/ik/
cd /home/elasticsearch/es/plugins/ik/
unzip elasticsearch-analysis-ik-1.9.2.zip
cd ../
chown elasticsearch:elasticsearch * -R
su - elasticsearch -c "./es/bin/elasticsearch"

重新测试,另行启动一个shell,用curl验证服务开启情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -XGET http://127.0.0.1:9200/?pretty

{
"name" : "Melody Guthrie",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.3.2",
"build_hash" : "b9e4a6acad4008027e4038f6abed7f7dba346f94",
"build_timestamp" : "2016-04-21T16:03:47Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}

可以发现,已成功开启。

三、为搜索引擎配置同义词

config/elasticsearch.yml中加入以下配置(使用原文作者建议,未深入研究):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
index:
analysis:
analyzer:
ik_syno:
type: custom
tokenizer: ik_max_word
filter: [my_synonym_filter]
ik_syno_smart:
type: custom
tokenizer: ik_smart
filter: [my_synonym_filter]
filter:
my_synonym_filter:
type: synonym
synonyms_path: analysis/synonym.txt

其中ik_syno会将文本做最细粒度的拆分,ik_syno_smart较前者而言,要更粗一些。
还可以在config/analysis/synonym.txt中加入同义词文件,如:

1
2
ua,user-agent,userAgent
Forward Secrecy =>FS

四、安装Marvel

Marvel是一个集群和数据管理界面,安装后能直接管理elasticsearch的数据。
在elasticsearch目录执行

1
2
bin/plugin install license
bin/plugin install marvel-agent

安装kibana依赖

1
2
3
4
wget https://download.elastic.co/kibana/kibana/kibana-4.5.0-linux-x64.tar.gz
tar -zxf kibana-4.5.0-linux-x64.tar.gz
mv kibana-4.5.0-linux-x64 kibana
vim config/kibana.yml

继续安装

1
bin/kibana plugin --install elasticsearch/marvel/latest

启动两个服务

1
2
bin/elasticsearch
bin/kibana

访问路径http://localhost:5601/app/marvel

五、其他

还包括JavaScript API、php API和全文搜素的实现,时间有限,还未来得及实现,下次再更。
附上参考来源,作者JerryQu。

搭建OpenVPN服务器(CentOS7)

OpenVPN是一个用于创建虚拟专用网络加密通道的软件包,OpenVPN允许创建的VPN使用公开密钥、电子证书、或者用户名/密码来进行身份验证。它大量使用了OpenSSL加密库中的SSLv3/TLSv1协议函数库。
目前OpenVPN能在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X与Microsoft Windows以及Android和iOS上运行,并包含了许多安全性的功能。它并不是一个基于Web的VPN软件,也不与IPsec及其他VPN软件包兼容。
OpenVPN的出现,也极大地方便了我们开发人员,在搭建OpenVPN的时候,我根据自己的实际情况,整理出相关的过程。

OpenVPN与easy-rsa的安装与配置

安装基础包

1
2
3
yum -y install openssl openssl-devel
yum -y install lzo
yum -y install openvpn easy-rsa

修改vars文件

1
2
cd /usr/share/easy-rsa/2.0/
vim vars

修改证书信息

1
2
3
4
5
6
export KEY_COUNTRY="CN"
export KEY_PROVINCE="GuangDong"
export KEY_CITY="Foshan"
export KEY_ORG="YateSun"
export KEY_EMAIL="xx@yatesun.com"
export KEY_OU="YateSun"

初始化环境变量

初始化,清除keys目录下所有与证书相关的文件,生成根证书及密钥。

1
2
3
source vars
./clean-all
./build-ca

生成服务端证书及密钥

一路按回车,直到提示需要输入y/n时,输入y再按回车,一共两次

1
./build-key-server server

生成客户端证书

每一个登陆的VPN客户端需要有一个证书,每个证书在同一时刻只能供一个客户端连接。为客户端生成证书和密钥。

1
./build-key client1

完美前向加密

创建迪菲·赫尔曼密钥,会生成dh2048.pem文件(生成过程比较慢,在此期间不要去中断它)

1
./build-dh

生成ta.key文件

防DDos攻击、UDP淹没等恶意攻击

1
openvpn --genkey --secret keys/ta.key

至此,所有生成的证书和密钥均位于/usr/share/easy-rsa/2.0/keys

服务端配置

新建文件夹及复制配置文件

在openvpn的配置目录下新建一个keys目录,将需要用到的openvpn证书和密钥复制一份到刚创建好的keys目录中。

1
2
mkdir /etc/openvpn/keys
cp /usr/share/easy-rsa/2.0/keys/{ca.crt,server.{crt,key},dh2048.pem,ta.key} /etc/openvpn/keys/

配置文件修改

配置文件位于/etc/openvpn/server.conf
执行以下命令

1
vim /etc/openvpn/server.conf

填入如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
port 443
proto tcp
dev tap
ca keys/ca.crt
cert keys/server.crt
key keys/server.key # This file should be kept secret
dh keys/dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.0.0 255.255.0.0"
;push "dhcp-option DNS 208.67.222.222"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth keys/ta.key 0 # This file is secret
comp-lzo
persist-key
persist-tun
status openvpn-status.log
log-append openvpn.log
verb 5

配置内核和防火墙

开启路由转发

1
2
sed -i '/net.ipv4.ip_forward/s/0/1/' /etc/sysctl.conf
sysctl -p

配置防火墙

1
2
3
iptables -I INPUT -p tcp --dport 443 -m comment --comment "openvpn" -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j MASQUERADE
service iptables save

配置OpenVPN服务

1
2
service openvpn start
chkconfig openvpn on

客户端配置文件

创建客户端连接文件

1
vim client.ovpn

填入如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
client
dev tap
proto tcp
remote 119.29.29.29 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca keys/ca.crt
cert keys/client.crt
key keys/client.key
ns-cert-type server
tls-auth keys/ta.key 1
comp-lzo
verb 5

在客户端执行以下命令:

1
openvpn client.ovpn

登录成功,OpenVPN搭建完成。

搭建Git服务器及客户端使用方法

Git服务器配置

添加用户git

1
adduser git

禁用shell登录

1
2
3
4
usermod -s /usr/bin/git-shell git
cd /home/git/
mkdir git-shell-commands
chmod 755 git-shell-commands

其中,登录的publickey位于:

1
/home/git/.ssh/authorized_keys

切换用户

1
su -s /bin/bash - git

初始化git仓库

初始化仓库yatesun,并对git用户赋权限。

1
2
3
cd repositories
git init --bare yatesun.git
chown git:git yatesun.git -R

克隆工作区

1
git clone -bare /home/git/hehe.git hehe

客户端使用Git

客户端Git配置

输入以下命令,可以搭建一个本地的git仓库。

1
2
3
4
5
git config --global user.name "Yate Sun"
git config --global user.email "yatesun@gmail.com"
mkdir git
cd git
git init

客户端从远程仓库克隆

1
git clone git@server:/path/to/yatesun.git

简单测试

1
2
3
4
5
cd yatesun
vim readme.md
git add readme.md
git commit -m "commit first"
git push

至此,新编辑的readme.md文件已经成功提交到Git服务器,可以通过以下命令查看Git状态:

1
git status

更新远程仓库到本地

1
git pull

HTTPS方式

1
2
mv hooks/post-update.sample hooks/post-update
git update-server-info

错误处理

问题

1
2
3
4
No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as 'master'.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to 'git@server:/path/to/code.git'

这是指Git未找到我即将要提交的代码版本。

解决方法

1
git push origin master

自动抓取必应首页壁纸

优质壁纸

必应搜索(bing.com)作为一个较为大型的搜索引擎,一直是一个最佳的壁纸网站,每天0点准时更新壁纸,并且图片质量非常不错。
本站一直抓取bing的首页图片,作为首页的封面,使用301跳转,意味着这张壁纸可能很大,但是不占用本站流量,使用的是bing.com的流量。同时还新增了返回https链接,便于HTTPS的网站能够显示小绿锁。
使用了memcache,每8个小时内,仅请求一次,减低延时,降低请求次数,没有安装memcache的情形下,可以先删除memcache相关代码。
其中,1920x1080.jpg可以修改为360x480.jpg1366x768.jpg等多种分辨率。

php代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?
/*
* 获取Bing每日壁纸 YateSun 2016.02.25
*/
$memcache = new Memcache();
//$memcache->addServer("127.0.0.1", 11211);//memcached
$memcache->connect('127.0.0.1', 11211);
$url = $memcache->get('imgurl');
if(!$url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$re = curl_exec($ch);
curl_close($ch);
$re = json_decode($re,1);//电脑版返回内容
$url=$re['images'][0]['url'];
//$url=str_replace("http://s.cn.bing.net","https://www.bing.com",$url);
$url="https://www.bing.com".$url;
$memcache->set('imgurl',$url,0,8*60*60);
}
//Header( "HTTP/1.1 301 Moved Permanently" ) ;
Header( "Location: ".$url );
?>

在所有需要用到壁纸的页面,只需要将图片的url地址改为/get.php即可。

HTTPS下部署多说评论

经过短暂的使用,多说对HTTPS提供了简单的支持,但并不全面,暂时发现还有以下三种情况没有得到解决:
1.默认的头像地址
2.评论中的表情图片地址
3.输入框的表情选择框中的图片地址
下面将逐步解决以上3种情况。

修改多说公共JS代码

找到如下这一行:

1
ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';

替换为:

1
ds.src = '/js/embed.js';

本地化embed.js

在embed.js中找到:

1
'+_(Z.avatarUrl(e,t))+'

替换为

1
/cdncache.php?url='+_(Z.avatarUrl(e,t))+'

HTTP转HTTPS的php代码

在source目录添加文件cdncache.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
//HTTP图片转HTTPS(防盗链) YateSun 2016.03.16
if(!(isset($_SERVER['HTTP_REFERER'])&&parse_url($_SERVER['HTTP_REFERER'])['hosts']='yatesun.com')){
die();
}
$url=urldecode($_REQUEST['url']);
if(preg_match("/^http/",$url)){
$opts = array('http'=>array('method'=>'GET','timeout'=>10));
$result = file_get_contents($url,FALSE,stream_context_create($opts));
if($result){
header("Cache-Control:public;maxage=604800");
header('Content-type: image/png');
echo $result;
}else{
header("HTTP/1.1 404 Not Found");
}
}else{
header("HTTP/1.1 403 Forbidden");
}
?>

不显示多说版权信息

http://yatesun.duoshuo.com/admin/settings/中,选择自定义CSS,加入:

1
#ds-thread .ds-powered-by{display:none !important;}

评论内容中表情及图片

http://yatesun.duoshuo.com/admin/settings/中,选择评论框选项,取消勾选:
1.允许插入表情
2.允许插入图片(需要同时开启下面的解析html代码)