PAC自动代理配置文件

PAC = Proxy Automatic Configuration 用来自动配置代理的,本来一直在用chrome的switchy插件,最近看了眼PAC,感觉比插件还简单一点,对我个人来说,平时需要翻的网站相对比较固定,使用的代理软件也很固定,相当于是“一次配置,到处运行”了

PAC文件内置的函数(http://findproxyforurl.com/pac-functions/ 抄一份自己用好查)

// If the hostname matches or contains google.com (e.g. maps.google.com, www.google.com),
// send direct to the Internet.
if (dnsDomainIs(host, ".google.com"))
    return "DIRECT";

// Any requests with a hostname ending with the extension .local
// will be sent direct to the Internet.
if (shExpMatch(url, "*.local"))
    return "DIRECT";

// If IP of requested website website falls within IP range, send direct to the Internet.
if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0"))
    return "DIRECT";

// If the machine requesting a website falls within IP range,
// send traffic via proxy 10.10.5.1 running on port 8080.
if (isInNet(myIpAddress(), "10.10.1.0", "255.255.255.0"))
    return "PROXY 10.10.5.1:8080";

// If IP of the requested host falls within any of the ranges specified, send direct.
if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
    isInNet(dnsResolve(host), "172.16.0.0",  "255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
    isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
    return "DIRECT";

// If user requests plain hostnames, e.g. http://intranet/, 
// http://webserver-name01/, send direct.
if (isPlainHostName(host))
    return "DIRECT";

// If the Host requested is "www" or "www.google.com", send direct.
if (localHostOrDomainIs(host, "www.google.com"))
    return "DIRECT";

// If hostname contains any dots, send via proxy1.example.com, otherwise send direct.
if (dnsDomainLevels(host) > 0)
    return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

// If during the period of Monday to Friday, proxy1.example.com will be returned, otherwise
// users will go direct for any day outside this period.
if (weekdayRange("MON", "FRI")) return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

// If during the period of January to March, proxy1.example.com will be returned, otherwise
// users will go direct for any month outside this period.
if (dateRange("JAN", "MAR")) return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

// If during the period 8am to 6pm, proxy1.example.com will be returned, otherwise
// users will go direct for any time outside this period.
if (timeRange(8, 18)) return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

// Outputs the resolved IP address of the host in the browser
// to end-user or error console. 
resolved_host = dnsResolve(host);
alert(resolved_host);

从内置的函数来看,PAC挺强大的,比如可以自动根据解析的地址选择是否使用代理,还可以根据不同的时间段来选择不同的代理

PAC文件调试

用浏览器调试

  • IE浏览器:直接可以看到alert输出(我测试了下有些诡异,具体表现是刷几次之后不弹出alert了,IE用的不多就不折腾了)
  • chrome浏览器:chrome://net-internals/#events
  • firefox浏览器:使用Error Console插件,在“消息”里可以看到pac的调试输出

用工具调试

  • https://code.google.com/p/pactester/ 用于测试PAC文件的perl脚本,似乎已经不再维护了
  • https://code.google.com/p/pacparser/ PAC解析工具(其实可以基于这个工具做一个在线测试PAC的页面)
  • windows也有工具可以用,下载地址https://code.google.com/p/pacparser/downloads/list
    • pactester.exe -p E:\developer\www\gfw-proxy.pac -u http://facebook.com
    • SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT;

参考资料

ubuntu下手动连接pptp

ubuntu下手动连接pptp-vpn

最近 Google 基本被墙了,Dropbox 彻底被墙了,无奈入手了一个 vpn,vpn 的原理是创建一个虚拟网卡,默认情况下会将默认网关设置为 vpn 的网关,也就是说所有流量都会走 vpn,这对于我们访问国内的网站是不方便的,于是有了 chnroute 项目, 看了下项目的 wiki,原理其实不复杂,简单来说就是在 vpn 启动之前,通过配置路由表的方式将国内的 ip 范围全部设置为直连,系统选择路由的时候会优先选择匹配度高的路由规则,如果没有才会选择默认路由规则。

本文记录的是ubuntu 12.04下手动连接pptp以及配置chnroute

clone chnroute项目

clone chnroute项目(也可以直接找生成好的路由表,通常几个月才有点变化),生成国内路由信息,根据提示将生成的文件cp到对应的目录。

安装pptp-linux

sudo pptpsetup --create ppp0 --client --server $server --username $username --password $password --encrypt --start
sudo poff ppp0 断开vpn连接
sudo pon ppp0 启用vpn连接

配置路由规则

pptp手动启动之后并不会添加默认路由,需要手动添加一下(可以自行加到ip-up.d/ip-down.d文件里去实现自动化)

sudo ip route del default
sudo ip route add default dev ppp0

vivi@ubuntu-ssd:~$ route -n | more
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 ppp0
1.0.1.0         192.168.1.1     255.255.255.0   UG    0      0        0 eth1
1.0.2.0         192.168.1.1     255.255.254.0   UG    0      0        0 eth1
1.0.8.0         192.168.1.1     255.255.248.0   UG    0      0        0 eth1
1.0.32.0        192.168.1.1     255.255.224.0   UG    0      0        0 eth1
1.1.0.0         192.168.1.1     255.255.255.0   UG    0      0        0 eth1
1.1.2.0         192.168.1.1     255.255.254.0   UG    0      0        0 eth1
...

修改dns /etc/resolv.conf

dns也要修改成8.8.8.8或者其他opendns配置,否则dropbox还是被dns污染的

验证效果

验证,浏览器访问

就成了

之前看到过一个吐嘈,说国外人民看到我朝普通网民都会各种操作route/iptables应该会很惊讶吧。。尼玛都是被逼的好吧

chnroute项目@github 国内ip数据来自APNIC

一台服务器运行多个tomcat实例

之前整理过的,贴出来备忘一下

一台服务器运行多个tomcat实例 how to run multiple tomcat instance on a single server.

理解几个概念

  • $CATALINA_HOME tomcat的安装目录,lib目录是tomcat用到的库,对tomcat所有instance可见,bin是tomcat启动停止脚本,用这个路径来查找bin和lib目录
  • $JAVA_HOME java的安装目录,一般是/usr/lib/jvm/java-xx-xx,通常会使用符号链接
  • $CATALINA_TMPDIR tomcat运行的临时目录
  • $CLASSPATH
  • $CATALINA_BASE 是用来配置多个instances的利器,如果这个值定义了,tomcat会使用这个值来计算以下目录的位置,而不使用CATALINA_HOME的值
  • conf contains configuration files and related DTDs. The most important file located here is server.xml.
  • logs holds log and output files.
  • webapps is where you put the applications.
  • work – Tomcat translates and converts any JavaServer Pages (JSP) into servlets and stores them here.
  • temp is used for temporary files.

默认$CATALINA_BASE是没有配置的,所以以上这些目录都会通过$CATALINA_HOME计算,也就是tomcat安装目录。

  • /usr/share/$NAME tomcat安装目录,启动脚本bin/,jar包lib/,也就是CATALINA_HOME需要设置的值
  • /var/lib/$NAME
  • /etc/$NAME
  • /etc/init.d/$NAME tomcat的启动/停止脚本,可以作为一个模板实现multiple instance的脚本

打开文件数量限制修改

修改 /etc/security/limits.conf(貌似要重启还是重新login)
vivi            soft    nofile          200000
vivi            hard    nofile          200000
ulimit -n "$MAX_FILEDESCRIPTORS" 注意这个值只能改成<=limits.conf里面设置的值

tomcat端口说明 Here is a list of the ports to change:

  • Shutdown port is used for shutting down Tomcat. When we call the shutdown.sh script, it sends a signal to shutdown port. If the Tomcat Java process receives the signal, it cleans up and exits.
  • HTTP port is the actual port that exposes the application to an outside client via HTTP.
  • ajp (Apache JServ Protocol) port may be used by a web server (such as the Apache httpd server) to communicate with Tomcat. This port is also used if you set up a load-balanced server.
  • Redirect port – If the Connector supports non-SSL requests and a request is received for which a security constraint requires SSL, Catalina will automatically redirect the request to this port.

Tomcat至少需要两个端口,Shutdown和HTTP,shutdown端口总是监听在本机localhost,所以是无法从远程发送shutdown命令的。

如果使用rotatelogs来做一天一个log文件

# Run the catalina.sh script as a daemon
set +e
touch "$CATALINA_PID"
rm -f "$CATALINA_BASE/logs/catalina.out"
mkfifo -m700 "$CATALINA_BASE/logs/catalina.out"
# Look for rotatelogs/rotatelogs2
if [ -x /usr/sbin/rotatelogs ]; then
          ROTATELOGS=/usr/sbin/rotatelogs
else
          ROTATELOGS=/usr/sbin/rotatelogs2
fi

# -p preserves the environment (for $JAVA_HOME etc.)
# -s is required because tomcat5.5's login shell is /bin/false
$ROTATELOGS -f $CATALINA_BASE/logs/catalina_%F.log 86400 \
                        < "$CATALINA_BASE/logs/catalina.out" &
chown $TOMCAT6_USER "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
start-stop-daemon --start -b -u "$TOMCAT6_USER" -g "$TOMCAT6_GROUP" \
        -c "$TOMCAT6_USER" -d "$CATALINA_TMPDIR" -p "$CATALINA_PID" \
        -x /bin/bash -- -c "$AUTHBIND_COMMAND $TOMCAT_SH"
status="$?"
# 需要注释掉/usr/share/tomcat.x/bin/catalina.sh里的一行,否则会碰到启动卡住catalina.out无法输出的问题
#touch "$CATALINA_OUT"

reference

linux命令-sed(stream editor)

linux命令-sed(stream editor)
sed的全称是stream editor,原来这货也算是个编辑器,这应该算是一个很geek的编辑器了吧 :)

基本参数说明

  • -n 关闭默认打印pattern space,例如使用p命令时一般需要加这个参数关闭默认打印
  • -r 使用扩展的正则表达式,\d\s等
  • -i inplace模式,输入文件将直接被修改

基本用法

sed 's/my/your/g' input.txt 将my替换成your
sed 's/my/your/1' input.txt 只替换第一个匹配
sed -n '/echo/=' input.txt 打印出包含echo的行号
sed '1i #!/bin/bash' input.txt 在第一行插入一行内容
sed '/echo/i # insert before' 匹配echo的行之前插入内容
sed '/echo/a # insert after' 匹配echo的行之后插入内容
sed '/echo/c # replace the line' 将匹配echo的行替换成指定的行内容
sed -r '/\s*<[^>]*>\s*/ /g' html.txt 将html标签替换成空格,测试似乎不能使用非贪婪模式<.*?>表达

用法总结(不总结一下每次都要google命令。。)

s 命令,替换匹配

sed '[line-address1][,line-address2]s/pattern/replacement/[index|g]' input.txt
替换line1-line2($表示最后一行)的第index个pattern为replacement(g表示全部替换,[index]g表示替换第index个到最后的匹配)

其中line-address可以是一个具体的行,也可以是一个匹配,例如
sed -n '/{/,/}/p' input.txt 打印包含{的行到包含}的行

i/a/c 命令,插入,追加,修改匹配行

sed '[line-address1][,line-address2][a|i|c] new-content' input.txt
sed '/pattern/[a|i|c] new-content' 以匹配的行为基准append/insert/change/delete内容。
sed '1,4c #line replaced' input.txt c模式下是把1-4行替换成一行新内容,而不是每行分别替换。

p/d 命令,打印/删除匹配行
与i/a/c命令类似,只是不需要提供[new-content]

一次处理多个匹配

sed '1,3s/my/your/g; 3,$/this/that/g' input.txt 等价于
sed -e '1,3s/my/your/g' -e '3,$/this/that/g' input.txt

命令嵌套打包
sed '1,${/this/d; s/^ *//g}' input.txt 如果匹配到this那么删除,否则删除行开头空格

参考资料

  • 简明sed教程 后面的hold space之类的概念瞄了一眼觉得应该用不着,先放着

linux命令-nc(netcat)

linux命令-nc(netcat)

今天才在《高性能MySQL》书里看到这个好用的linux命令行工具,有了这个工具之后服务器之间临时要传个文件什么的,会变得很简单

先看下没有这个命令之前我是怎么在两台服务器之间传输文件的

  1. 不需要ssh的情况下,使用python的SimpleHTTPServer和wget …
# 先到源服务器,cd到要传输文件所在的目录,利用python自带的HTTPServer模块起一个简单的web服务器
vivi@ubuntu-ssd:~$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
# 然后再到目标服务器,使用wget把文件下载下来。。。如果有文件夹的话就tar打包一下
vivi@ubuntu-ssd:~$ wget http://source-server-ip:8000/file.txt
  1. 需要ssh的情况下,例如从本地传一个文件到服务器上(或者从服务器上下载一个文件)
    scp -i /path/to/private.key -P 22 /path/to/local/file.txt username@remote-server:/path/to/dest/folder/
    -r 参数传输目录
    tar -czvf - /path/to/file.txt | ssh username@server "tar -xzvf - -C /path/to/file.txt"
    
  2. 使用filezilla,上传/下载/折腾/不解释

nc(netcat)

The nc (or netcat) utility is used for just about anything under the sun involving TCP or UDP. It can open TCP connections, send UDP packets,
listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6. Unlike telnet(1), nc scripts nicely, and separates
error messages onto standard error instead of sending them to standard output, as telnet(1) does with some.

常用参数说明

  • -l 监听端口,而不是连到远程端口
  • -q interval 接收到EOF之后等待interval秒后退出

传输单个文件

  • 目标服务器: nc -l 12345 -q 1 > /path/to/file.txt
  • 发送服务器: nc remote-server 12345 < /path/to/file.txt

传输大文件或者文件夹,可以配合tar打包压缩传输

  • 目标服务器:nc -l 12345 -q 1 | tar -xzvf -
  • 发送服务器:tar -czvf - /path/to/source/folder | nc remote-server 12345

另外说下如果tar要解压到非当前目录,那么参数是 -C /path/to/dest/folder/ 而不是想当然的 tar -xzvpf /path 这个形式其实是提取压缩包指定的一个文件。