通过ssh tunnel和nginx从外网访问本地服务

在某些情况下, 需要让外网能够访问本地正在开发的网站, 例如做微信开发,微信API接受消息的url必须是外网可访问的地址,我们不可能每次修改代码再发布到外网服务器进行调试,通常可以通过ngrok来实现,使用ngrok就不需要拥有自己的外网服务器,但ngrok有时候还是有点慢, 而且每次地址都会变,当然也有国内的类似服务如natapp, natapp免费版本有各种限制,想想也不好用,虽然我也没用过。 但如果有一台外网服务器, 那么通过ssh tunnel和nginx就可以轻松实现从外网访问local的服务,这样就不用每次都发布到外网服务。下面将讲解如何实现。

前提条件:有一台外网可以访问的服务器

基本思路: 通过ssh建立一个通道,把远程外网机器上的一个端口和本地的端口建立起一个连接,远程机器机器上的那个端口的访问请求通过ssh tunnel转到本地机器的端口,而本地机器的这个端口也就是你web服务的端口,例如apache/tomcat/nginx的80或8080端口,这样就使得本地机器可在外网可以访问了

例如你的外网机器可以通过myhost.com访问(或者直接使用ip也可以),在本地机器运行如下命令:

ssh -nNT -R 8000:localhost:80 user@myhost.com
上面的命令就建立起了外网机器8000端口和本地机器80端口的通道,当访问外网机器8000端口时, 请求会被ssl tunnel转到本地机器的80端口,这样就已经实现了我们的目的,但是…
微信官方明确要求:
微信公众号接口只支持80接口
不知道为什么腾讯要做这个限制,但我们肯定不愿意一台机器唯一的宝贵80端口只用来做微信开发,好在nginx可以解决这个问题,配置如下:
server {
    listen 80;
    server_name myhost.com www.myhost.com;
    root /var/www;

    location /wechat/ {
        rewrite /wechat/(.*) /$1 break;
        proxy_pass http://127.0.0.1:8000;
        error_log /var/www/logs/wechat_error.log;
        access_log /var/www/logs/wechat_access.log;
    }
}
这样80端口还是可以用于其它的网站,url包含/wechat/的请求会被转到8000端口, 然后再转到本地机器的80端口, 在微信开发平台就可以大致设置url为http://myhost.com/wechat/receive, 相对应的本地localhost/receive用于接受微信的消息。
使用ssh tunnel和nginx相比于ngrok的好处有:
1. 如果是国内的服务器, 速度应该比ngrok快
2. 地址固定, 不会像ngrok那样每次都变,这样就省去每次都去微信开发平台设置url的时间,而且如果使用ngrok服务的话,通常需要点击好几次才能保存成功
补充:
上面的方法对微信消息的收发是没有问题的, 但对于微信网页开发就有一些问题了, 因为涉及到认证、url跳转, 静态资源(js/css/image)的访问,下面就这些问题提出一个更好的方案,那就是专门为微信开发新建一个二级域名,例如:wechat.myhost.com, 新建 nginx server如下:
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /usr/local/nginx/ssl/nginx.crt;
    ssl_certificate_key /usr/local/nginx/ssl/nginx.key;
    server_name wechat.myhost.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
    }
    error_log /mnt/www/logs/wechat_error.log;
    access_log /mnt/www/logs/wechat_access.log;
}
当然也得把那个二级域名加到本地机器的server name 里
server {
    listen 80;
    server_name wechat.dev wechat.myhost.com;
    ...

gem install – error : Connection reset by peer

sudo gem install cocoapods

ERROR:  Could not find a valid gem ‘cocoapods’ (>= 0), here is why:

          Unable to download data from https://rubygems.org/ – Errno::ECONNRESET: Connection reset by peer – SSL_connect (https://rubygems.org/latest_specs.4.8.gz)

上面这个错误可能是由于GFW引起了, 所以把source rubygems.org改成baobao.com就可以了

$ gem sources --remove https://rubygems.org/
$ gem sources -a https://ruby.taobao.org/
$ gem sources -l
*** CURRENT SOURCES ***

https://ruby.taobao.org

更多详情见 https://ruby.taobao.org/

php null empty

NULL

The special NULL value represents a variable with no value. NULL is the only possible value of type null.

A variable is considered to be null if:

  • it has been assigned the constant NULL.

  • it has not been set to any value yet.

  • it has been unset().


empty

emptyDetermine whether a variable is empty

Description

bool empty ( mixed $var )

Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.

Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.

The following things are considered to be empty:

  • “” (an empty string)
  • 0 (0 as an integer)
  • 0.0 (0 as a float)
  • “0” (0 as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • $var; (a variable declared, but without a value)