生命之中的最大错误在于:终日担心犯错误。— 爱尔伯特·哈伯德 (Elbert Hubbard 1856-1915),《笔记》
ssh账号代理上网是很常见的,尤其是翻越障碍物的时候很实用。
ssh账号是可以登录linux系统的,如果只是上网用,那就需要最小化权限,有两个方式:
1 /bin/false
2 自定义脚本
输入字符后会退出,不会产生系统操作
ssh账号是可以登录linux系统的,如果只是上网用,那就需要最小化权限,有两个方式:
1 /bin/false
useradd -s /bin/false yourUser
#登录时使用这样的:
ssh -D 7070 -N yourUser@hostname
#登录时使用这样的:
ssh -D 7070 -N yourUser@hostname
2 自定义脚本
cat /bin/tunnel.sh
#!/bin/sh
echo "##########"
echo " welcome !"
echo "##########"
read x
exit
useradd -s /bin/tunnel.sh yourUser
ssh -D 7070 yourUser@hostname
#!/bin/sh
echo "##########"
echo " welcome !"
echo "##########"
read x
exit
useradd -s /bin/tunnel.sh yourUser
ssh -D 7070 yourUser@hostname
输入字符后会退出,不会产生系统操作
相信有些服务器还是无可奈何的使用windows作为服务器,比如需要运行asp
可是要灵活rewrite和防盗链之类的,IIS可就麻烦了,一个不愿多碰的玩意
既然需要用,那就可以使用一个灵活的web服务在前面,后面放IIS,让它好好的退居二线。
一线位置的可选软件有:Nginx和apache
两者都可以提供足够的灵活性,如果还需要运行php,那不妨安装一些套件,比如:
我习惯用后者,用起来也还挺方便。
相对而言,apache的一些代理功能并非很灵活,用起来就有点复杂了。比如用正则匹配的方式条件性的进行代理,这个需要2.2.5版本以上才支持。nginx还是很不错的一个选择,代理功能非常强大,配置简洁,前端服务器的不二选择,各个大型网站都开始启用nginx,使用量风风火火的往上爬。
可是要灵活rewrite和防盗链之类的,IIS可就麻烦了,一个不愿多碰的玩意
既然需要用,那就可以使用一个灵活的web服务在前面,后面放IIS,让它好好的退居二线。
一线位置的可选软件有:Nginx和apache
两者都可以提供足够的灵活性,如果还需要运行php,那不妨安装一些套件,比如:
引用
XAMPP - XAMPP是一款具有中文说明的功能全面的集成环境,XAMPP并不仅仅针对Windows,而是一个适用于Linux、Windows、Mac OS X 和Solaris 的易于安装的Apache 发行版。软件包中包含Apache 服务器、MySQL、SQLite、PHP、Perl、FileZilla FTP Server、Tomcat等等。默认安装开放了所有功能,安全性有问题,需要进行额外的安全设定。
WampServer - WampServe集成了Apache、MySQL、PHP、phpmyadmin,支持Apache的mod_rewrite,PHP扩展、Apache模块只需要在菜单“开启/关闭”上点点就搞定,省去了修改配置文件的麻烦。
AppServ - 集成了Apache、PHP、MySQL、phpMyAdmin,较为轻量。
WampServer - WampServe集成了Apache、MySQL、PHP、phpmyadmin,支持Apache的mod_rewrite,PHP扩展、Apache模块只需要在菜单“开启/关闭”上点点就搞定,省去了修改配置文件的麻烦。
AppServ - 集成了Apache、PHP、MySQL、phpMyAdmin,较为轻量。
我习惯用后者,用起来也还挺方便。
相对而言,apache的一些代理功能并非很灵活,用起来就有点复杂了。比如用正则匹配的方式条件性的进行代理,这个需要2.2.5版本以上才支持。nginx还是很不错的一个选择,代理功能非常强大,配置简洁,前端服务器的不二选择,各个大型网站都开始启用nginx,使用量风风火火的往上爬。
引用
ProxyPassMatch Directive
Description: Maps remote servers into the local server URL-space using regular expressions
Syntax: ProxyPassMatch [regex] !|url [key=value [key=value ...]]
Context: server config, virtual host, directory
Status: Extension
Module: mod_proxy
Compatibility: available in Apache 2.2.5 and later
Description: Maps remote servers into the local server URL-space using regular expressions
Syntax: ProxyPassMatch [regex] !|url [key=value [key=value ...]]
Context: server config, virtual host, directory
Status: Extension
Module: mod_proxy
Compatibility: available in Apache 2.2.5 and later
比如,把asp的请求放到8080端口的服务器
<VirtualHost *:80>
ServerAdmin webmaster@aslibra.com
DocumentRoot "E:/webapps/www.aslibra.com"
ServerName www.aslibra.com
ErrorLog "logs/test.localhost-error.log"
CustomLog "logs/test.localhost-access.log" common
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPassMatch .*\.asp http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
ServerAdmin webmaster@aslibra.com
DocumentRoot "E:/webapps/www.aslibra.com"
ServerName www.aslibra.com
ErrorLog "logs/test.localhost-error.log"
CustomLog "logs/test.localhost-access.log" common
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPassMatch .*\.asp http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
这个会对给proxy带来很大的灵活性,参考官方介绍:
http://httpd.apache.org/docs/current/mod/mod_proxy.html
Nginx的代理功能太完善了,我们看看proxy_redirect参数的作用。
案例说明:
要做一个html.aslibra.com的域名处理很多网站的html内容,当然是后端的服务器了,目录分析
html.zcom.com/img.aslibra.com/
html.zcom.com/css.aslibra.com/
访问的域名是该目录下的域名,那前端nginx的配置应该类似这样:
但这样访问目录时如果没有以“/”结尾,则服务器会返回301redirect:
html.aslibra.com这个域名并非公布的域名,返回给客户端是会自然产生错误的
Nginx可以很好的处理这个问题:
加一行proxy_redirect后,正常了:
就这么样就ok啦~
不过貌似不支持变量出现在地址里,这个就郁闷了,必须指定相应域名。
对于多个域名匹配的server,redirect设置不能写作'/'了,否则会用第一个域名作为redirect域名
可以写几个匹配规则:
案例说明:
要做一个html.aslibra.com的域名处理很多网站的html内容,当然是后端的服务器了,目录分析
html.zcom.com/img.aslibra.com/
html.zcom.com/css.aslibra.com/
访问的域名是该目录下的域名,那前端nginx的配置应该类似这样:
server {
server_name img.aslibra.com;
location / {
rewrite ^(.*) /$http_host$1 break;
proxy_set_header Host html.aslibra.com;
proxy_pass http://cache-89;
}
}
server_name img.aslibra.com;
location / {
rewrite ^(.*) /$http_host$1 break;
proxy_set_header Host html.aslibra.com;
proxy_pass http://cache-89;
}
}
但这样访问目录时如果没有以“/”结尾,则服务器会返回301redirect:
[root@aslibra ~]# curl -I http://img.aslibra.com/www
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.59
Date: Tue, 21 Jul 2009 15:28:58 GMT
Connection: keep-alive
Location: http://html.aslibra.com/img.aslibra.com/www/
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.59
Date: Tue, 21 Jul 2009 15:28:58 GMT
Connection: keep-alive
Location: http://html.aslibra.com/img.aslibra.com/www/
html.aslibra.com这个域名并非公布的域名,返回给客户端是会自然产生错误的
Nginx可以很好的处理这个问题:
server {
server_name img.aslibra.com;
location / {
rewrite ^(.*) /$http_host$1 break;
proxy_set_header Host html.aslibra.com;
proxy_pass http://cache-89;
proxy_redirect http://html.aslibra.com/img.aslibra.com/ /;
}
}
server_name img.aslibra.com;
location / {
rewrite ^(.*) /$http_host$1 break;
proxy_set_header Host html.aslibra.com;
proxy_pass http://cache-89;
proxy_redirect http://html.aslibra.com/img.aslibra.com/ /;
}
}
加一行proxy_redirect后,正常了:
[root@aslibra ~]# curl -I http://img.aslibra.com/www
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.59
Date: Tue, 21 Jul 2009 15:23:49 GMT
Content-Type: text/html
Location: http://img.aslibra.com/www/
Connection: keep-alive
Content-Length: 185
Expires: Tue, 21 Jul 2009 16:23:49 GMT
Cache-Control: max-age=3600
HTTP/1.1 301 Moved Permanently
Server: nginx/0.7.59
Date: Tue, 21 Jul 2009 15:23:49 GMT
Content-Type: text/html
Location: http://img.aslibra.com/www/
Connection: keep-alive
Content-Length: 185
Expires: Tue, 21 Jul 2009 16:23:49 GMT
Cache-Control: max-age=3600
就这么样就ok啦~
不过貌似不支持变量出现在地址里,这个就郁闷了,必须指定相应域名。
对于多个域名匹配的server,redirect设置不能写作'/'了,否则会用第一个域名作为redirect域名
可以写几个匹配规则:
proxy_redirect http://html.aslibra.com/img.aslibra.com/ http://img.aslibra.com/;
proxy_redirect http://html.aslibra.com/css.aslibra.com/ http://css.aslibra.com/;
proxy_redirect http://html.aslibra.com/css.aslibra.com/ http://css.aslibra.com/;
正向代理和反向代理是forward/reverse proxy的意思,在代理功能上来讲,有一点不太一样。
举个例子:
你要去租房,你找房屋中介找房子,房屋中介找房屋的全权代理人要房子,房屋的全权代理人是由户主委托的。
这里有四个角色:
你=client
房屋中介=forword proxy
代理人=reverse proxy
户主=server
客户端访问网络如果需要指定某个代理服务器为你去获取内容,那就是正向代理
而服务器隐藏在代理服务器后面,让代理服务器作为冲锋陷阵的,那这个代理服务器就是反向代理
而squid是一个 forword/reverse proxy,两个功能兼备,一般可以作为局域网的上网缓存,此时作为正向代理。
一般服务器会让squid作为前端,那就是充当反向代理,反向代理有很多软件都可以,比如nginx、lighttpd,但他们两个一般做不了正向代理。
举个例子:
你要去租房,你找房屋中介找房子,房屋中介找房屋的全权代理人要房子,房屋的全权代理人是由户主委托的。
这里有四个角色:
你=client
房屋中介=forword proxy
代理人=reverse proxy
户主=server
客户端访问网络如果需要指定某个代理服务器为你去获取内容,那就是正向代理
而服务器隐藏在代理服务器后面,让代理服务器作为冲锋陷阵的,那这个代理服务器就是反向代理
而squid是一个 forword/reverse proxy,两个功能兼备,一般可以作为局域网的上网缓存,此时作为正向代理。
一般服务器会让squid作为前端,那就是充当反向代理,反向代理有很多软件都可以,比如nginx、lighttpd,但他们两个一般做不了正向代理。
Nginx的代理功能很强大,主要体现在可以设置返给后端服务器的http头信息,这一点可以让我们方便的实现很多需求。
比如要做一个镜像,这个当然有可能是好事。
http://a.aslibra.com/s/main.jpg
我需要访问 http://b.aslibra.com/s/main.jpg 也是一样的内容呢?
利用缓存功能就可以了,以上例子还加上了简单破解防盗链的方法,就是加上正确的referer的头信息就可以了
upstream自己可以设定,修改了host的信息,使得相当于本地访问backend使用了要做镜像的域名。
同理,要多个域名是一样的内容是,那可以多个域名使用同样的server设定,简单的指定host值即可,不列举了。
比如要做一个镜像,这个当然有可能是好事。
http://a.aslibra.com/s/main.jpg
我需要访问 http://b.aslibra.com/s/main.jpg 也是一样的内容呢?
server {
server_name b.aslibra.com;
root /Data/webapps/b.aslibra.com;
error_page 404 = @fetch;
location @fetch {
internal;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_set_header Host a.aslibra.com;
proxy_set_header referer http://a.aslibra.com/;
proxy_pass http://backend;
root /Data/webapps/b.aslibra.com;
}
}
server_name b.aslibra.com;
root /Data/webapps/b.aslibra.com;
error_page 404 = @fetch;
location @fetch {
internal;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_set_header Host a.aslibra.com;
proxy_set_header referer http://a.aslibra.com/;
proxy_pass http://backend;
root /Data/webapps/b.aslibra.com;
}
}
利用缓存功能就可以了,以上例子还加上了简单破解防盗链的方法,就是加上正确的referer的头信息就可以了
upstream自己可以设定,修改了host的信息,使得相当于本地访问backend使用了要做镜像的域名。
同理,要多个域名是一样的内容是,那可以多个域名使用同样的server设定,简单的指定host值即可,不列举了。
问题示例:
网站有千万个网页文件需要存储,占用空间大约有300-400G,导致问题:
1 小文件太多,备份困难
2 空间增长很难调整
3 前端做缓存,因为object很高,效率很低,squid和lighttpd都不合适
解决方案说明:
1 nginx+memcached接口
Nginx有一个模块是可以读取memcached的数据的,可以把网页文件内容保存到memcached里面,如果数据无效,则proxy到后端,后端服务器更新此数据
2 memcachedb接口
memcachedb是新浪的一个开源项目,用硬盘作为存储空间,用的是Berkeley DB的存储引擎,memcached的协议。
有memcached的方便性,同时有高效的读写性能,没有内存作为存储空间的限制,数据永久保留,同时使用局域网的机器就可以处理并且很容易共享,不限制为本地文件,有自动的备份机制。
3 php程序管理存储
php处理memcached很容易,和前端约定相应的key即可
4 计划任务处理更新
由于memcachedb是永久保存,前端无法判断是否过期,所以需要自己制定策略删除过期的网页,以便前端获取不到而自动更新
5 magent作为memcachedb的代理接口,解决备份问题
memcachedb有备份方法,我碰到过出现无法同步的情况,magent也可以帮助解决此问题,它是为memcached设计的,但由于memcachedb使用memcached协议,所以也同样适用
解决方案配置示例:
假设www.aslibra.com/article/xxx 地址需要使用此方案,那就可以用服务器A(2)和B(3)作为memcachedb服务,可以在A(2)上跑magent,C(4)服务器是后端服务器,负责存入memcachedb数据
前端Nginx配置判断:
定义了memcachedb的upstream,有一个是backup标识的
/article/的请求会先查询memcachedb,找不到再发送到后端服务器
注意 proxy_set_header memcached_key $memcached_key 这句,可以保持key值的一致性
对于中文出现在地址的情况很实用,后端使用$_SERVER['REQUEST_URI'] 会和 $uri 不一致
A和B缓存服务器:
如果配置主从,那可以启用magent:
C服务器配置rewrite(lighttpd):
PHP代码参考:
删除文件:
如果有记录日志(可以是web服务器日志或者php记录的日志),可以根据保存的日志处理
需要删除的 $m->delete($key) 即可
备份请参考memcachedb的操作指南。
此解决方案适合memcached的存储方式,况且不用处理过期的问题,php可以解决过期时间
文章更新请关注本文更新:
http://www.aslibra.com/blog/post/memcachedb_cache_solution.php
参考资料:
1 Berkeley DB
2 memcachedb
3 magent
4 NginxModules
5 嵌入式数据库系统Berkeley DB
6 memcached和magent的安装
7 memcachedb的安装
网站有千万个网页文件需要存储,占用空间大约有300-400G,导致问题:
1 小文件太多,备份困难
2 空间增长很难调整
3 前端做缓存,因为object很高,效率很低,squid和lighttpd都不合适
解决方案说明:
1 nginx+memcached接口
Nginx有一个模块是可以读取memcached的数据的,可以把网页文件内容保存到memcached里面,如果数据无效,则proxy到后端,后端服务器更新此数据
2 memcachedb接口
memcachedb是新浪的一个开源项目,用硬盘作为存储空间,用的是Berkeley DB的存储引擎,memcached的协议。
有memcached的方便性,同时有高效的读写性能,没有内存作为存储空间的限制,数据永久保留,同时使用局域网的机器就可以处理并且很容易共享,不限制为本地文件,有自动的备份机制。
3 php程序管理存储
php处理memcached很容易,和前端约定相应的key即可
4 计划任务处理更新
由于memcachedb是永久保存,前端无法判断是否过期,所以需要自己制定策略删除过期的网页,以便前端获取不到而自动更新
5 magent作为memcachedb的代理接口,解决备份问题
memcachedb有备份方法,我碰到过出现无法同步的情况,magent也可以帮助解决此问题,它是为memcached设计的,但由于memcachedb使用memcached协议,所以也同样适用
解决方案配置示例:
假设www.aslibra.com/article/xxx 地址需要使用此方案,那就可以用服务器A(2)和B(3)作为memcachedb服务,可以在A(2)上跑magent,C(4)服务器是后端服务器,负责存入memcachedb数据
前端Nginx配置判断:
upstream backend {
server 192.168.1.4;
}
upstream memcachedb {
server 192.168.1.2:11212;
server 192.168.1.3:11212 backup;
}
server {
server_name www.aslibra.com;
location / {
proxy_pass http://backend;
}
location ~* ^/article/ {
set $memcached_key $host$uri;
default_type text/html;
memcached_pass memcachedb;
error_page 404 = /fallback;
}
location = /fallback {
internal;
proxy_set_header memcached_key $memcached_key;
proxy_pass http://backend;
}
}
server 192.168.1.4;
}
upstream memcachedb {
server 192.168.1.2:11212;
server 192.168.1.3:11212 backup;
}
server {
server_name www.aslibra.com;
location / {
proxy_pass http://backend;
}
location ~* ^/article/ {
set $memcached_key $host$uri;
default_type text/html;
memcached_pass memcachedb;
error_page 404 = /fallback;
}
location = /fallback {
internal;
proxy_set_header memcached_key $memcached_key;
proxy_pass http://backend;
}
}
定义了memcachedb的upstream,有一个是backup标识的
/article/的请求会先查询memcachedb,找不到再发送到后端服务器
注意 proxy_set_header memcached_key $memcached_key 这句,可以保持key值的一致性
对于中文出现在地址的情况很实用,后端使用$_SERVER['REQUEST_URI'] 会和 $uri 不一致
A和B缓存服务器:
memcachedb -p 11212 -l 0.0.0.0 -u root -d -r -N -H /data/aslibra.com/article/
如果配置主从,那可以启用magent:
magent -s 192.168.1.2:11212 -b 192.168.1.3:11212
#默认监听 0.0.0.0:11211,提供给PHP使用
#比如这里是在192.168.1.2上运行
#默认监听 0.0.0.0:11211,提供给PHP使用
#比如这里是在192.168.1.2上运行
C服务器配置rewrite(lighttpd):
$HTTP["host"] == "www.aslibra.com" {
server.document-root = "/data/www.aslibra.com/"
url.rewrite-once = (
"^/article" => "/php/cache.php"
)
}
server.document-root = "/data/www.aslibra.com/"
url.rewrite-once = (
"^/article" => "/php/cache.php"
)
}
PHP代码参考:
<?
//do sth to build html
echo $html;
//如果有传递memcached_key值就把结果存入memcachedb
//不需要设置缓存时间,因为没有用 :)
//有需要更新,那就记录一下日志
if($_SERVER['HTTP_MEMCACHED_KEY']){
$m = new Memcache;
if($m->connect('192.168.1.2', 11211) ){
$key = $_SERVER['HTTP_MEMCACHED_KEY'];
$m->set($key, $html);
//有必要就记日志
//log to file...
}
}
?>
//do sth to build html
echo $html;
//如果有传递memcached_key值就把结果存入memcachedb
//不需要设置缓存时间,因为没有用 :)
//有需要更新,那就记录一下日志
if($_SERVER['HTTP_MEMCACHED_KEY']){
$m = new Memcache;
if($m->connect('192.168.1.2', 11211) ){
$key = $_SERVER['HTTP_MEMCACHED_KEY'];
$m->set($key, $html);
//有必要就记日志
//log to file...
}
}
?>
删除文件:
如果有记录日志(可以是web服务器日志或者php记录的日志),可以根据保存的日志处理
需要删除的 $m->delete($key) 即可
备份请参考memcachedb的操作指南。
此解决方案适合memcached的存储方式,况且不用处理过期的问题,php可以解决过期时间
文章更新请关注本文更新:
http://www.aslibra.com/blog/post/memcachedb_cache_solution.php
参考资料:
1 Berkeley DB
2 memcachedb
3 magent
4 NginxModules
5 嵌入式数据库系统Berkeley DB
6 memcached和magent的安装
7 memcachedb的安装





