使用 Nginx 做翻墙代理

配置

/etc/nginx/nginx.conf 配置,可以采用自签名证书,客户端连的时候不 verify 证书即可。

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
    worker_connections 10240;
}

http {
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" '
    '"upstream=$upstream_addr" "scheme=$scheme"     "X-Remote-App=$http_x_remote_app" "reqtime=$request_time"     "upstream_resptime=$upstream_response_time"     "$upstream_cache_status" "host=$host"';
    ssl_certificate /etc/nginx/ssl/52.77.252.184.crt;
    ssl_certificate_key /etc/nginx/ssl/52.77.252.184.key;
    ssl_session_cache shared:SSL:100m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SH    A256:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AE    S128-SHA:DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Load modular configuration files from the     /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/server.conf 配置。

#
# A virtual host using mix of IP-, name-, and port-based configuration
#

server {
    listen 443 ssl;
    server_name _;

    access_log /var/log/nginx/443_access.log main;
    resolver 8.8.8.8;

    set $upstream_endpoint $host;

    location / {
        proxy_pass https://$upstream_endpoint;
    }
}

server {
    listen 80;
    server_name _;

    access_log /var/log/nginx/80_access.log main;
    resolver 8.8.8.8;

    set $upstream_endpoint $host;

    location / {
        proxy_pass http://$upstream_endpoint;
    }
}

测试

要修改 header,而且 curl 要加 -k 不 verify 证书。

$ curl -k -I -H "Host:play.google.com" "https://52.77.252.184/store/apps/details?hl=en&id=tr.com.fugo.kelimeavi2.en"
HTTP/1.1 200 OK

$ curl -k -I -H "Host:www.baidu.com" http://52.77.252.184
HTTP/1.1 200 OK

这样翻墙的好处是可以有多台 Nginx,程序能够控制访问哪台 Nginx。

搭建 sniproxy

sniproxy 源码在 https://github.com/dlundquist/sniproxy,它的作用是:

Proxies incoming HTTP and TLS connections based on the hostname contained in the initial request of the TCP session.

 

安装:

rpm -ivh http://mirror.zhoufengjie.cn/centos/el6/x86_64/RPMS/tyumenmirror-1.0-1.el6.noarch.rpm

yum -y install sniproxy

如果使用源码编译,最要把 udns 编译进去,否则如果配置 .* *:443 类似规则的时候会报:Only socket address backends are permitted when compiled without libudns

 

修改配置文件 /usr/local/sniproxy/etc/sniproxy.conf:

user daemon
pidfile /var/run/sniproxy.pid

error_log {
  syslog daemon
  priority notice
}

listen 443 {
  protocol tls
  table https_hosts

  access_log {
    filename /var/log/sniproxy.log
  }
}

table https_hosts {
  .* *:443
}

listen 80 {
  protocol http
  table http_hosts

  access_log {
    filename /var/log/sniproxy.log
  }
}

table http_hosts {
  .* *:80
}

table {
  .* 127.0.0.1
}

启动:

/usr/local/sniproxy/sbin/sniproxy -c /usr/local/sniproxy/etc/sniproxy.conf

 

然后修改 /etc/hosts 测试:

52.221.229.x play.google.com
52.221.229.x www.baidu.com

# curl -I “https://play.google.com/store/apps/details?hl=en&id=tr.com.fugo.kelimeavi2.en”
HTTP/1.1 200 OK

# curl -I http://www.baidu.com
HTTP/1.1 200 OK

都是 OK 的。

 

修改 hosts 很麻烦,可以使用  dnsmasq 来管理你的解析,在 dnsmasq 上把你需要的域名修改成你的 sniproxy,配合 dnscrypt,防止 DNS 被污染。详情请看:

https://www.logcg.com/archives/981.html

https://gist.github.com/tawateer/fff8798407693d74b80d44e46806cc82

 

python requests 信任自签名证书

我在一台 Nginx 上搭建 https 服务,证书使用自签名的证书,然后使用 Python 访问 https 服务。

 

解决方法1:

#!/bin/env python

import requests

url = "https://52.77.252.184/test.txt"

ret = requests.get(url, verify="/tmp/ssl/requests_test.crt")
print ret.status_code

通过 verify 指定证书,表示相信此证书(requests_test.crt 是服务器端证书);也可以用 verify=False,表示不验证服务器端的证书。

 

解决方法2:

设置环境变量 REQUESTS_CA_BUNDLE:
export REQUESTS_CA_BUNDLE=/tmp/ssl/requests_test.crt

然后使用 request 访问。

#!/bin/env python

import requests

url = "https://52.77.252.184/test.txt"

ret = requests.get(url)
print ret.status_code

搭建邮箱服务器遇到的发送邮件的问题

我在机房搭建了几台 Postfix,代理机房机器给公司邮箱发邮件( 公司使用 Gmail ),默认邮件会被谷歌拒收,这里需要注意一下。

 

1. SPF。

Sender Policy Framework (SPF) records allow domain owners to publish a list of IP addresses or subnets that are authorized to send email on their behalf.  The goal is to reduce the amount of spam and fraud by making it much harder for malicious senders to disguise their identity.  To learn more, visit the SPF Website.

SPF 的规则是:

接收方会验证发送方的公网 IP,如果接收方域名的 SPF 记录中包含这个 IP,认为是正确的邮件,否则认为是伪造的。

举个例子: 13_F7_9T$T}WM61VQTE`O[GD

2JN23o423osrwerwe

23G234o23u4nsdf

v=spf1 表示是第一版的 SPF;

include 表示包含这个域名的 SPF;

~all 表示如果都不匹配,SoftFail,如果 -all,表示都不匹配直接 Fail,如果 +all,表示通过,SPF 规则就无用了,如果 ?all 表示 Neutral,中立,你自己看着办。

此外,还有几个机制:

mx,表示如果发送方 IP 在此域名的 mx 记录解析结果里,通过;

a,比如 a:mx1.nosa.me a:mx2.nosa.me,如果发送方 IP 在 a 指定的域名解析结果中,那么通过;

ptr,比如 ptr:otherdomain1.com ptr:otherdomain2.com,官方解释:The hostname or hostnames for the client IP are looked up using PTR queries. The hostnames are then validated: at least one of the A records for a PTR hostname must match the original client IP. Invalid hostnames are discarded. If a valid hostname ends in domain, this mechanism matches。官方建议关闭,因为会带来大量的解析查询。

 

更多的机制看这里:

http://www.openspf.org/SPF_Record_Syntax

http://www.spfwizard.net/  这个网站可以生成 SPF ( TXT ) 记录。

 

2. DKIM。

DomainKeys Identified Mail (DKIM)  对邮件进行签名,防止内容被篡改。

在 Centos 下可以使用 dkim-milter 这个包(或者 opendkim ),比如:

EBDB8091-78E0-4522-B54F-97883FBDDDC4

通过在 dkim-filter.conf 配置使用 mx 这两个文件,mx.private 是私钥,mx.txt 则是包含公钥,看下 mx.txt 的内容:

mx._domainkey IN TXT “v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2dzV0IjYa76/Wc0WLMFhv4eCeZZX1mudLzQ003siBr1XG1oCnrPRClPchpPYigdODj/hyAP5tqHpaV8yskjgHByAL4WzsqxV6N8JPyrxejLfR+TN/Q3FTDvyLJZgsr6JuaHPO2hCT6ymNk/TbAX3VbDjJltLkc3GI/gcKWtm1TQIDAQAB” ; —– DKIM mx for nosa.me

此时解析一下 mx._domainkey.nosa.me TXT,可以看到:

99D80393B