Apache基于规则的访问控制

Apache提供了许多工具,允许管理员控制对服务器提供的特定资源的访问。 您可能已经熟悉基于身份验证的访问控制,这需要访问者在访问资源之前对服务器进行身份验证。
相比之下,Apache的基于规则的访问控制允许您指定哪些访问者在非常细微的级别访问哪些资源。 您可以创建规则,阻止来自Web服务器的指定IP范围,或者访问特定资源,甚至访问特定的虚拟主机。
基于规则的访问控制的最基本的使用是对通过网络连接可访问的资源施加严格的限制。 在默认Apache配置中,Web服务器拒绝所有用户访问系统上的所有文件。 然后Apache允许管理员允许访问特定资源。
这些访问规则的附加用途包括阻止恶意流量的特定IP范围,并且在许多其他可能性中将对给定资源或资源组的访问限制为“内部用户”。

基于规则的访问控制的示例

下面是一个基本规则的例子:

  1. Order Deny,Allow
  2. Deny from all
  3. Allow from 192.168.2.101

Order Deny,Allow指令告诉Web服务器在Allow规则之前应该处理“Deny”规则。
Deny from all指令告诉Web服务器所有用户被拒绝访问给定资源。 此规则优先执行。
Allow from指令告诉Web服务器应该允许源自IP地址192.168.2.101的请求。 这是最后处理,并表示拒绝所有规则的例外。
简而言之,除192.168.2.101之外的所有主机都被拒绝访问此资源。

其他访问控制规则

您可以通过修改和扩展上面的示例为资源指定精细的访问控制规则。 以下注释和建议提供了对这些访问控制系统可能实现的一些更高级功能的深入了解。

控制指定范围IP的访问

如果要控制指定范围IP地址的访问,而不是单个地址,Apache允许使用以下语法:

  1. Order Deny,Allow
  2. Deny from all
  3. Allow from 192.168
  4. Allow from 10

上述语句允许以192.168和10开头的所有地址。这些IP范围通常保留给本地网络,不是公共可路由地址。 如果使用这些访问控制规则,将只允许来自本地的流量。
这是访问规则的另一个示例:

  1. Order Allow,Deny
  2. Allow from all
  3. Deny from 185.201.1

此规则允许任何人访问给定资源,然后拒绝以185.201.1开头的所有IP地址的访问。 此语句将覆盖源自185.201.1.0到185.201.1.255的IP地址范围的所有流量。
当创建访问控制规则时,特别是那些使用Allow from all指令的规则,应该非常确定这些指令位于正确的上下文中。

高级访问控制

尽管基于IP地址设置访问控制规则是控制访问的最简单的方法,但Apache提供了许多其他方法。
首先,Apache允许管理员根据请求者的主机名来允许或拒绝访问。 这会强制Apache对执行请求的主机名执行反向DNS(rDNS)查找,然后根据此信息允许或拒绝访问。 考虑这个例子:

  1. Order Deny,Allow
  2. Deny from all
  3. Allow from hostname.example.com

Apache仅允许来自具有hostname.example.com的有效rDNS的计算机的请求访问此配置中的资源。
其次,可以在HTTP会话中围绕环境变量构建访问规则。 这允许您根据变量(例如浏览器(用户代理)和引荐来源)允许和拒绝对资源的访问。 让我们来看下面的例子:
SetEnvIf Referer searchenginez.com search_traffic
Order Deny,Allow
Deny from all
Allow from env=search_traffic
此访问控制规则与Apache的mod_setenvif结合使用。 首先,如果请求referrer匹配searchenginez.com,则设置环境变量search_traffic。 接下来,拒绝所有主机访问资源。 最后,设置了允许访问资源环境变量为search_traffic的请求。 有关设置和使用环境变量的更多信息,请参考mod_setenvif的官方Apache文档。

使用Apache Web服务器重定向URL

当HTTP资源或网页更改位置时,提供某些方法来提醒用户这些资源已移动通常很重要。 HTTP协议提供了通过与客户端应用通信的多个“重定向”状态码用于实现此目的而不影响用户体验。
Apache提供了许多“重定向”配置指令,允许管理员在配置文件中指定资源以重定向到另一个URL。 当请求被重定向时,服务器返回该请求的结果,该结果指示客户端发起针对目标资源的新位置的第二请求。
重定向可以告诉客户端所请求的页面已临时或永久移动。 Apache提供了轻松支持这些功能的工具。 本指南介绍了重定向配置指令,介绍如何设置各种重定向选项,以及如何将资源请求类重定向到新位置。

Redirect指令

重定向配置指令可以位于“主”服务器配置文件中,但我们建议您将它们保留在虚拟主机条目或目录块中。 也可以在.httaccess文件中声明重定向语句。 以下是Redirect指令的示例:
Apache配置选项:

  1. Redirect /username http://team.example.com/~username/

如果没有给出参数,则发送临时(例如302)重定向状态。 在这种情况下,客户端(用户代理)被通知在/username的可用资源已临时移动到http://team.example.com/~username/。
要指定特定的HTTP重定向状态,请指定以下状态之一:

  1. Redirect permanent /username http://team.example.com/~username/
  2. Redirect temp /username http://team.example.com/~username/
  3. Redirect seeother /username http://team.example.com/~username/
  4. Redirect gone /username

此重定向告诉客户端资源已永久移动,这对应于HTTP状态301.“temp”状态是默认行为,指定重定向仅是临时的; 这对应于HTTP状态302.“另一个”状态发送表示所请求的资源已被另一个资源替换的信号(HTTP状态303)。 最后,“gone”状态告诉客户端资源已被删除(永久); 这发送HTTP状态410,作为不可用的“404”状态的替代。 在“已离开”重定向的情况下,请忽略最终到达网址。
您还可以指定特定的HTTP代码,如下所示。

  1. Redirect 301 /username http://team.example.com/~username/
  2. Redirect 302 /username http://team.example.com/~username/
  3. Redirect 303 /username http://team.example.com/~username/
  4. Redirect 410 /username

Apache还提供了两个额外的永久和临时重定向指令,这些指令更清楚一些。 它们如下:

  1. RedirectPermanent /username/bio.html http://team.example.com/~username/bio/
  2. RedirectTemp /username/bio.html http://team.example.com/~username/bio/

此外,Apache还可以使用RedirectMatch指令使用正则表达式重定向一类请求到新地址。 例如:

  1. RedirectMatch (.*).jpg$ http://static.example.com$1.jpg

此指令与对具有.jpg扩展名的文件的任何请求进行匹配,并将其替换为第二个域上的位置。 因此:
http://www.example.com/avatar.jpg的请求将重定向到http://static.example.com/avatar.jpg和对http://www.example.com/images/avatar.jpg的请求将被重定向到http://static.example.com/images/avatar.jpg。

Apache设置文件访问密码保护

虽然大多数Web服务器内容创建为可供公众使用,但您可能希望将某些或所有网站限制为特定用户或组。 HTTP Auth允许您轻松创建这些限制。
本文介绍基于凭证和基于规则的Apache访问控制工具。

Apache访问控制

要为目录启用密码,请将以下行插入Apache配置文件的相应部分。 您还可以在.htaccess文件或虚拟主机配置部分中插入身份验证信息。 所需的指令是:
Apache配置文件:

  1. AuthType Basic
  2. AuthUserFile /var/www/example.com/.htpasswd
  3. AuthName "Sign In Here To Gain Access To the Site"
  4. Require valid-user

Apache在与客户端连接时用AuthType指令指定应使用的认证方法。 Basic类型要求密码作为明文在网络上发送。 因此,我们不建议使用此来保护敏感资源。
AuthUserFile指定存储密码的密码文件的路径(完整)。 在本例中,我们使用路径/var/www/example.com/.htpassword。 这是public_html文件夹之上的一个目录,防止意外暴露文件。 默认情况下,以.ht开头的所有文件在Apache的大多数默认配置中都不是Web可访问的,但不应假定。
AuthName指令包含用于浏览器通知用户服务器正在验证什么资源的提示。 该值是任意的。
Require valid-user告诉Apache任何有效的用户都可以进行身份验证。

生成HTTP AUTH密码

要生成密码,我们需要htpasswd工具。 对于许多发行版,此工具可能在您安装Apache本身时已安装。 Debian和Ubuntu用户必须使用以下命令安装apache2-utils软件包:

  1. sudo apt-get install apache2-utils

要指定用户创建文件,执行以下命令:

  1. htpasswd -c /var/www/example.com/.htpasswd username

在本例中,我们使用-c选项创建一个新的AuthUserFile。 该文件位于/var/www/example.com/.htpasswd,用户名为username。 htpasswd将提示您输入密码,然后确认密码。 如果文件存在,请用-c选项覆盖。
-b选项允许您把密码作为命令的最后一个参数,如下例所示:

  1. htpasswd -b /srv/auth/.htpasswd username 5t1ck6

AuthUserFile类似如下:
/var/www/example.com/.htpasswd

  1. hobby:isiA3Q4djD/.Q
  2. admin:{SHA}x9VvwHI6dmgk9VTE0A8o6hbCw2s=
  3. username:$apr1$vVzQJxvX$6EyHww61nnZr6IdQv0pVx/

带组的访问控制列表

在Require指令中,我们指定了valid-user。 这告诉Apache,任何可以对AuthUserFile中指定的用户进行身份验证的用户都可以访问该网站。 虽然可以为不同的资源维护单独的密码文件,但对于具有复杂身份验证需求的部署,这是很难维护的。
为了满足这一需求,Apache允许您使用单个AuthUserFile,包含需要向服务器进行身份验证的所有用户。 要将有效凭据集限制到.htpasswd文件中列出的特定用户子集,我们必须在Require配置参数中指定用户。 只有在Require user指令后指定的用户才能被允许访问指定的资源。 例如:
Apache配置文件选项:

  1. Require user username admin

给定这个指令,用户username和admin将能够登录资源。 可以在Require行上指定任何用户子集。 Apache还提供了将用户组织成组的能力,然后允许基于组成员资格访问资源。 此设置的配置指令如下所示:
Apache配置文件:

  1. AuthType Basic
  2. AuthUserFile /srv/auth/.htpasswd
  3. AuthGroupFile /srv/auth/.htgroup
  4. Require group Authorized

在这个例子中,我们引用了相同的AuthUserFile,但是我们添加了一个指定用户组的AuthGroupFile。 组文件包含用户组列表和与每个组相关联的用户名。 htgroup文件(如htpasswd文件)可以位于文件系统上的任何位置。 为了清晰起见,我们建议htgroup与htpasswd文件在同一目录中。 这里是一个htgroup文件的例子:
/var/www/example.com/.htgroup:

  1. Authorized: username username2
  2. Team: admin hobby

给定此htgroup文件,只有用户username和username2将有权访问上面列出的资源。 组文件的语法遵循一个简单的[groupname]:[username 1] [username 2] […]。 您可以将您的AuthUserFile中的任何用户名作为特定资源所需的组条目。

Debian 7 (Wheezy)安装配置Apache mod_fastcgi PHP-FPM

本文介绍如何在Debian 7系统上配置和安装使用Apache mod_fastcgi和PHP-FPM。 Apache的默认配置使用mod_php而不是mod_fastcgi,mod_php使用大量的系统资源。
mod_php使用更多资源的主要原因是因为它即使为非PHP文件(如纯HTML和JavaScript文件)也加载。 FastCGI进程管理器(PHP-FPM)通过强制Web服务器充当代理并且仅将以php文件扩展名结尾的文件传递给PHP-FPM来帮助减少所使用的系统资源量。
此外,使用PHP-FPM允许将每个虚拟主机配置为作为单独用户运行PHP代码。 以前,这只能通过使用suPHP。

安装mod_fastcgi和PHP-FPM

mod_fastcgi和PHP-FPM都在Debian 7官方软件库,安装方法如下:
1.更新软件库

  1. sudo apt-get update && sudo apt-get upgrade –show-upgraded

2.看看mod_fastcgi是否可用。 默认情况下,Debian 7不包括安装mod_fastcgi所需的软件库,因为它是一个contrib模块,并且是non-free的(就Debian的许可限制而言)。

  1. sudo apt-cache search libapache2-mod-fastcgi

3.如果不可用,您需要编辑/etc/apt/sources.list文件,以允许将contrib和non-free软件加载到软件库列表中。 您的源文件应如下所示:
/etc/apt/sources.list:

  1. deb http://ftp.es.debian.org/debian stable main contrib non-free
  2. deb-src http://ftp.es.debian.org/debian stable main contrib non-free
  3.  
  4. deb http://ftp.debian.org/debian/ wheezy-updates main contrib non-free
  5. deb-src http://ftp.debian.org/debian/ wheezy-updates main contrib non-free
  6.  
  7. deb http://security.debian.org/ wheezy/updates main contrib non-free
  8. deb-src http://security.debian.org/ wheezy/updates main contrib non-free

4.更新apt-get软件库

  1. sudo apt-get update && sudo apt-get upgrade –show-upgraded

5.安装mod_fastcgi和PHP-FPM

  1. sudo apt-get install libapache2-mod-fastcgi php5-fpm

配置Apache使用PHP-FPM

我们现在将配置Apache将PHP文件的所有请求(带有PHP文件扩展名)通过FastCGI传递给PHP wrapper。
1.激活mod_actions模块

  1. sudo a2enmod actions

2.配置PHP-FPM使用UNIX套接字而不是TCP。 在这个命令中,我们将使用grep来确定套接字是否已被使用。

  1. sudo grep -E ‘^s*listens*=s*[a-zA-Z/]+’ /etc/php5/fpm/pool.d/www.conf

你会看到如下输出:
listen = /var/run/php5-fpm.sock
如果你看到如上输出,请跳到第6步。
3.如果没有看到以上输出,更改如下文件:
etc/php5/fpm/pool.d/www.conf

  1. listen = /var/run/php5-fpm.sock

4.找到如下行并删除
/etc/php5/fpm/pool.d/www.conf:

  1. listen = 127.0.0.1:9000

5.重启php5-fpm生效配置

  1. sudo service php5-fpm restart

6.检查Apache版本

  1. apache2 -v

7.根据Apache版本,编辑对应的文件
Apache 2.2或更早版本
/etc/apache2/mods-enabled/fastcgi.conf:

  1. <IfModule mod_fastcgi.c>
  2.  AddType application/x-httpd-fastphp5 .php
  3.  Action application/x-httpd-fastphp5 /php5-fcgi
  4.  Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
  5.  FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization
  6. </IfModule>

Apache 2.4或更高版本
/etc/apache2/mods-enabled/fastcgi.conf

  1. <IfModule mod_fastcgi.c>
  2.  AddType application/x-httpd-fastphp5 .php
  3.  Action application/x-httpd-fastphp5 /php5-fcgi
  4.  Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
  5.  FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization
  6.  <Directory /usr/lib/cgi-bin>
  7.   Require all granted
  8.  </Directory>
  9. </IfModule>

8.保存文件并检查配置错误

  1. sudo apache2ctl configtest

9.只要你看到Syntax OK输出,重启Apache服务

  1. sudo service apache2 restart

如果没有看到Syntax OK,检查下配置哪里出错了
10.通过创建和访问具有phpinfo()显示的页面来检查PHP是否正常工作。 以下命令将在/var/www(Apache中网站的默认目录)中创建info.php:

  1. sudo echo "<?php phpinfo(); ?>" > /var/www/info.php

CentOS 6安装配置Apache Web服务器

安装Apache

1.安装Apache HTTP服务器

  1. sudo yum install httpd

2.编辑Apache配置文件调整资源占用配置。下面的配置适合2GB内存服务器使用。
/etc/httpd/conf/httpd.conf:

  1. KeepAlive Off
  2.  
  3.  
  4. <IfModule prefork.c>
  5.     StartServers        4
  6.     MinSpareServers     20
  7.     MaxSpareServers     40
  8.     MaxClients          200
  9.     MaxRequestsPerChild 4500
  10. </IfModule>

配置Apache虚拟主机

1.在/etc/httpd/conf.d目录创建vhost.conf文件。把example.com域名替换为你的
/etc/httpd/conf.d/vhost.conf:

  1. <VirtualHost *:80>
  2.      ServerAdmin [email protected]
  3.      ServerName example.org
  4.      ServerAlias www.example.org
  5.      DocumentRoot /srv/www/example.org/public_html/
  6.      ErrorLog /srv/www/example.org/logs/error.log
  7.      CustomLog /srv/www/example.org/logs/access.log combined
  8. </VirtualHost>

2.创建相关目录

  1. sudo mkdir -p /srv/www/example.org/public_html
  2. sudo mkdir -p /srv/www/example.org/logs

3.启动Apache

  1. sudo service httpd start

4.设置Apache开机启动

  1. sudo chkconfig httpd on

Apache模块及脚本

安装Apache模块

默认情况下,模块位于/etc/httpd/modules/目录中。 默认模块的配置指令位于/etc/httpd/conf/httpd.conf中,而使用yum安装的可选模块的配置选项通常位于/etc/httpd/conf.d/中的.conf文件中。
1.列出可用Apache模块

  1. sudo yum search mod_

2.安装所需模块

  1. sudo yum install mod_[module-name]

安装脚本支持

下面的命令安装相应模块以使Apache支持服务端脚本语言PHP,Python和Perl。
Perl支持:

  1. sudo yum install mod_perl

Python支持:

  1. sudo yum install mod_wsgi

PHP支持:

  1. sudo yum install php php-pear

Ubuntu 12.04 LTS (Precise Pangolin)安装配置Apache

Apache HTTP Web服务器(Apache)是非常受欢迎的开源Web服务器软件。 本指南解释如何在Ubuntu 12.04 LTS上安装和配置Apache Web服务器。

安装Apache

1.安装Apache2 web服务器,它的文档及工具。

  1. sudo apt-get install apache2 apache2-doc apache2-utils

2.编辑Apache配置文件,调整资源使用配置。下面的配置适用于2G内存服务器。
/etc/apache2/apache2.conf:

  1. KeepAlive Off
  2.  
  3.  
  4. <IfModule mpm_prefork_module>
  5.     StartServers        4
  6.     MinSpareServers     20
  7.     MaxSpareServers     40
  8.     MaxClients          200
  9.     MaxRequestsPerChild 4500
  10. </IfModule>

配置Apache

Apache支持基于名称的虚拟主机,允许你在只有一个IP的服务器上托管多个域名的虚拟主机。虽然有多种方法设置虚拟主机,不过推荐使用如下的方法。
1.禁用默认虚拟主机

  1. sudo a2dissite 000-default.conf

2.使用文本编辑器在/etc/apache2/sites-available中创建一个example.com.conf文件,用您自己的域URL替换配置文件和文件名中example.com:
/etc/apache2/sites-available/example.com.conf:

  1. <VirtualHost *:80>
  2.      ServerAdmin [email protected]
  3.      ServerName example.com
  4.      ServerAlias www.example.com
  5.      DocumentRoot /var/www/example.com/public_html/
  6.      ErrorLog /var/www/example.com/logs/error.log
  7.      CustomLog /var/www/example.com/logs/access.log combined
  8. </VirtualHost>

如果需要添加多个虚拟主机,重复以下步骤。
3.创建网站目录及日志目录

  1. sudo mkdir -p /var/www/example.com/public_html
  2. sudo mkdir /var/www/example.com/logs

4.激活网站

  1. sudo a2ensite example.com.conf

5.重启Apache

  1. sudo systemctl restart apache2

Apache模块及脚本支持

安装Apache模块

Apache的优势之一是能够使用模块进行定制。 Apache模块的默认安装目录是/etc/apache2/mods-available/目录。
1.列出可用的Apache模块

  1. sudo apt-cache search libapache2*

2.安装任何想要的模块

  1. sudo apt-get install [module-name]

3.所有的模块都位于/etc/apache2/mods-available目录中。 如果需要,编辑任何已安装模块的.conf文件,然后启用模块

  1. sudo a2enmod [module-name]

禁用目前已启用的模块

  1. a2dismod [module-name]

安装脚本支持模块

下面的命令安装的模块是使Apache支持服务端脚本语言PHP,Ruby,Python和Perl。支持这些语言是可选的,可以根据你的需求安装。
Ruby支持:

  1. sudo apt-get install libapache2-mod-ruby

Perl支持:

  1. sudo apt-get install libapache2-mod-perl2

Python支持:

  1. sudo apt-get install libapache2-mod-python

Python支持MySQL:

  1. sudo apt-get install python-mysqldb

PHP支持:

  1. sudo apt-get install libapache2-mod-php5 php5 php-pear php5-xcache

php5-suhosin – PHP安全模块:

  1. sudo apt-get install php5-suhosin

PHP支持MySQL:

  1. sudo apt-get install php5-mysql

Ubuntu 14.04 (Trusty Tahr)安装配置Apache mod_wsgi

WSGI规范为动态Web应用程序与Web服务器通信提供了一种标准和高效的方法。 mod_wsgi提供了一个用Apache简单部署WSGI应用程序的方法。 WSGI用于部署使用框架和工具(如Django,Web.py,Werkzug,Chery.py,TurboGears和Flask)编写的应用程序。

安装依赖

执行如下命令安装依赖

  1. apt-get install apache2 python-setuptools libapache2-mod-wsgi

配置WSGI处理器

为了使mod_wsgi能够对您的应用程序提供访问支持,您需要在应用程序目录中创建一个application.wsgi文件。 应用程序目录应位于DocumentRoot外部。 以下三个部分每个呈现一个不同的application.wsgi示例文件,以说明此文件的基本结构:

Hello World WSGI配置

在此示例中,应用程序存储在/var/www/html/example.com/application目录中。 修改此示例和所有以下示例以符合部署中使用的实际文件和位置。
/var/www/html/example.com/application/application.wsgi:

  1. import os
  2. import sys
  3.  
  4. sys.path.append(‘/var/www/html/example.com/application’)
  5.  
  6. os.environ[‘PYTHON_EGG_CACHE’] = ‘/var/www/html/example.com/.python-egg’
  7.  
  8. def application(environ, start_response):
  9.     status = ‘200 OK’
  10.     output = ‘Hello World!’
  11.  
  12.     response_headers = [(‘Content-type’, ‘text/plain’),
  13.                         (‘Content-Length’, str(len(output)))]
  14.     start_response(status, response_headers)
  15.  
  16.     return [output]

您必须将应用程序的路径追加到系统路径。 PYTHON_EGG_CACHE变量的声明是可选的,但在使用Web服务器的权限执行WSGI脚本时,某些应用程序可能需要声明。

Web.py WSGI配置

在此示例中,Web.py应用程序嵌入在application.wsgi文件中。 必须安装Web.py Framework才能使以下应用程序成功运行。
/var/www/html/example.com/application/application.wsgi:

  1. import web
  2.  
  3. urls = (
  4.     ‘/(.*)’, ‘hello’
  5. )
  6.  
  7. class hello:       
  8.     def GET(self, name):
  9.         if not name:
  10.             name = ‘World’
  11.         return ‘Hello, ‘ + name + ‘!’
  12.  
  13. if __name__ == "__main__":
  14.     app.run()
  15.  
  16. app = web.application(urls, globals(), autoreload=False)
  17. application = app.wsgifunc()

Django WSGI配置

以下示例的application.wsgi文件为Django应用程序的配置:
/var/www/html/example.com/application/application.wsgi:

  1. import os
  2. import sys
  3.  
  4. sys.path.append(‘/var/www/html/example.com/application’)
  5.  
  6. os.environ[‘PYTHON_EGG_CACHE’] = ‘/var/www/html/example.com/.python-egg’
  7.  
  8. os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘settings’
  9.  
  10. import django.core.handlers.wsgi
  11. application = django.core.handlers.wsgi.WSGIHandler()

在使这个例子能正常工作之前,你的系统必须已经安装有一个正常工作的Django应用程序。 DJANGO_SETTINGS_MODULE指向您的应用程序的“settings.py文件”,在本示例的情况下,该文件位于/var/www/html/example.com/application/settings.py。

配置Apache

部署以下虚拟主机配置并修改路径和域名以符合你应用程序的要求:

  1. <VirtualHost *:80>
  2.    ServerName example.com
  3.    ServerAlias www.example.com
  4.    ServerAdmin [email protected]
  5.  
  6.    DocumentRoot /var/www/html/example.com/public_html
  7.  
  8.    ErrorLog /var/www/html/example.com/logs/error.log
  9.    CustomLog /var/www/html/example.com/logs/access.log combined
  10.  
  11.    WSGIScriptAlias / /var/www/html/example.com/application/application.wsgi
  12.  
  13.    Alias /robots.txt /var/www/html/example.com/public_html/robots.txt
  14.    Alias /favicon.ico /var/www/html/example.com/public_html/favicon.ico
  15.    Alias /images /var/www/html/example.com/public_html/images
  16.    Alias /static /var/www/html/example.com/public_html/static
  17. </VirtualHost>

在这个例子中,WSGIScriptAlias指令告诉Apache VirtualHost,所有请求由指定的WSGI脚本处理。 四个Alias指令允许Apache直接从DocumentRoot提供robots.txt和favicon.ico文件以及/ images和/ static位置下的所有资源,而无需WSGI应用程序的参与。 您可以根据需要添加任意数量的Alias配置参数。
虚拟主机配置好后,重启Apache

  1. service apache2 restart

每次application.wsgi文件更改时,您都需要重新启动Web服务器。 但是,对应用程序的所有其他修改不需要重新启动Web服务器。 恭喜! 您现在已经使用mod_wsgi成功部署了WSGI应用程序。

rsync增量传输大文件优化技巧

问题

rsync用来同步数据非常的好用,特别是增量同步。但是有一种情况如果不增加特定的参数就不是很好用了。比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步。但是发现等了好久都没有进行数据传输,倒是机器的IO一直居高不下。

原因

rsync具体的增量同步算法不太清楚。根据它的表现来看,可能在增量同步已经存在的一个文件时,会校验已传输部分数据是否已源文件一致,校验完成才继续增量同步这个文件剩下的数据。所以如果对一个大文件以这样的算法来增量同步是非常花时间并且占用IO资源的。

方法

半夜花了一个多小时查看了rsync的文档,发现有一个参数能快速恢复大文件的增量同步,–append。设置–append参数会在增量同步时计算文件大小并直接追加新的数据到文件,这样就省了费IO校验的过程。不过这个参数最好只在源文件和目标文件都不会更改的时候使用比较安全,比如备份的文件。

nginx-upload-module模块实现文件上传(multipart/form-data和断点续传)

前言

有时候我们想简单实现文件上传的功能,又不想使用额外的语言(比如PHP、Java),或者想实现文件的断点续传。这个时候Nginx的一个模块nginx-upload-module就能满足我们的需求。

模块安装

下载模块:

  1. cd /tmp
  2. wget https://codeload.github.com/vkholodkov/nginx-upload-module/zip/2.2
  3. unzip 2.2

安装模块:

  1. .configure –add-module=/tmp/nginx-upload-module-2.2/

multipart/form-data表单上传示例

nginx.conf配置:

  1. server {
  2. […]
  3.         location /upload {
  4.                 upload_pass @uploadHandler;
  5.                 upload_store /usr/local/nginx/upload_temp 1;
  6.                 upload_set_form_field $upload_field_name.path "$upload_tmp_path";
  7.         }
  8.  
  9.         location @uploadHandler {
  10.                 proxy_pass http://backend-host;
  11.         }
  12. […]
  13. }

这里在server里定义了upload location,这个location是上传的接口,还有@uploadHandler location,是当文件上传完成后,nginx模块会对这个location发送一些必要的信息,如文件上传的路径。
这里涉及了几个指令:

  • upload_pass @uploadHandler: 上传完成后会发送必要的数据到@uploadHandler;
  • upload_store /usr/local/nginx/upload_temp 1: 文件上传的临时目录;
  • upload_set_form_field $upload_field_name.path “$upload_tmp_path”: 设置文件上传完成后,把文件临时路径发送给upload_pass指定的location。

断点续传示例

nginx.conf配置

  1. server {
  2. […]
  3.         location /resumable_upload {
  4.                 upload_resumable on;
  5.                 upload_state_store /usr/local/nginx/upload_temp ;
  6.                 upload_pass @drivers_upload_handler;
  7.                 upload_store /usr/local/nginx/upload_temp;
  8.                 upload_set_form_field $upload_field_name.path "$upload_tmp_path";
  9.         }
  10.  
  11.         location @resumable_upload_handler {
  12.                 proxy_pass http://localhost:8002;
  13.         }
  14. […]
  15. }

与上一步multipart/form-data表单上传示例配置不同的地方有:

  • upload_resumable on: 开启断点续传功能;
  • upload_state_store /usr/local/nginx/upload_temp: 设置断点续传状态文件存储的目录。

上传文件第一个片段

  1. POST /upload HTTP/1.1
  2. Host: example.com
  3. Content-Length: 51201
  4. Content-Type: application/octet-stream
  5. Content-Disposition: attachment; filename="big.TXT"
  6. X-Content-Range: bytes 0-51200/511920
  7. Session-ID: 1111215056
  8.  
  9. <0-51200的字节文件数据>

上传文件第一个片段服务器响应

  1. HTTP/1.1 201 Created
  2. Date: Thu, 02 Sep 2010 12:54:40 GMT
  3. Content-Length: 14
  4. Connection: close
  5. Range: 0-51200/511920
  6.  
  7. 0-51200/511920

上传文件最后一个片段

  1. POST /upload HTTP/1.1
  2. Host: example.com
  3. Content-Length: 51111
  4. Content-Type: application/octet-stream
  5. Content-Disposition: attachment; filename="big.TXT"
  6. X-Content-Range: bytes 460809-511919/511920
  7. Session-ID: 1111215056
  8.  
  9. <460809-511919字节文件数据>

上传文件最后一个片段服务器响应

  1. HTTP/1.1 200 OK
  2. Date: Thu, 02 Sep 2010 12:54:43 GMT
  3. Content-Type: text/html
  4. Connection: close
  5. Content-Length: 2270
  6.  
  7. <响应的内容>

请求头说明

请求头 说明
Content-Disposition attachment, filename=“上传的文件名”
Content-Type 待上传文件的mime type,如application/octet-stream(注:不能为multipart/form-data)
X-Content-Range 待上传文件字节范围,如第一片段bytes 0-51200/511920,最后一个片段bytes 460809-511919/511920(注:文件第一个字节标号为0,最后一个字节标号为n-1,其中n为文件字节大小)
X-Session-ID 上传文件的标识,由客户端随机指定.因为是断点续传,客户端必须确保同一个文件的所有片段上传标识一致
Content-Length 上传片段的大小

Python上传demo

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*- 
  3.  
  4.  
  5. import os.path
  6. import requests
  7. import hashlib
  8.  
  9. # 待上传文件路径
  10. FILE_UPLOAD = "/tmp/testfile"
  11. # 上传接口地址
  12. UPLOAD_URL = "http://host/drivers_upload"
  13. # 单个片段上传的字节数
  14. SEGMENT_SIZE = 1048576
  15.  
  16. def upload(fp, file_pos, size, file_size):
  17.     session_id = get_session_id()
  18.     fp.seek(file_pos)
  19.     payload = fp.read(size)
  20.     content_range = "bytes {file_pos}-{pos_end}/{file_size}".format(file_pos=file_pos,
  21.                     pos_end=file_pos+size-1,file_size=file_size)
  22.     headers = {‘Content-Disposition’: ‘attachment; filename="big.TXT"’,’Content-Type’: ‘application/octet-stream’,
  23.                 ‘X-Content-Range’:content_range,’Session-ID’: session_id,’Content-Length’: size}
  24.     res = requests.post(UPLOAD_URL, data=payload, headers=headers)
  25.     print(res.text)
  26.  
  27.  
  28. # 根据文件名hash获得session id
  29. def get_session_id():
  30.     m = hashlib.md5()
  31.     file_name = os.path.basename(FILE_UPLOAD)
  32.     m.update(file_name)
  33.     return m.hexdigest()
  34.  
  35. def main():
  36.     file_pos = 0
  37.     file_size = os.path.getsize(FILE_UPLOAD)
  38.     fp = open(FILE_UPLOAD,"r")
  39.  
  40.     while True:
  41.         if file_pos + SEGMENT_SIZE >= file_size:
  42.             upload(fp, file_pos, file_size – file_pos, file_size)
  43.             fp.close()
  44.             break
  45.         else:
  46.             upload(fp, file_pos, SEGMENT_SIZE, file_size)
  47.             file_pos = file_pos + SEGMENT_SIZE
  48.  
  49. if __name__ == "__main__":
  50.     main()

参考

https://www.nginx.com/resources/wiki/modules/upload/
http://www.grid.net.ru/nginx/upload.en.html

Nginx反向代理谷歌

这几天谷歌都被某墙折腾得不能用了啊。上谷歌搜索资料都要翻越某墙,真悲摧啊。干脆自己用国外的一个vps反向代理谷歌吧。下面贴出我反向代理谷歌的nginx配置,造福人类。
假设用devops.webres.wang反向代理谷歌,是假设,我可不愿意由于这个博客被墙。

  1. proxy_cache_path  /data/nginx/cache/one  levels=1:2   keys_zone=one:10m max_size=10g;
  2. proxy_cache_key  "$host$request_uri";
  3. server {
  4. listen 80;
  5. server_name devops.webres.wang webres.wang;
  6. rewrite ^(.*) http://devops.webres.wang$1 permanent;
  7. }
  8.  
  9. upstream google {
  10.  server 74.125.224.80:80 max_fails=3;
  11.  server 74.125.224.81:80 max_fails=3;
  12.  server 74.125.224.82:80 max_fails=3;
  13.  server 74.125.224.83:80 max_fails=3;
  14.  server 74.125.224.84:80 max_fails=3;   
  15.  }
  16. server {
  17.         listen      443;
  18.         server_name  devops.webres.wang webres.wang;
  19.          ssl on;
  20.     ssl_certificate /usr/local/nginx/conf/centos.crt;
  21.     ssl_certificate_key /usr/local/nginx/conf/centos.key;
  22. location / {
  23.                 proxy_cache one;
  24.                 proxy_cache_valid  200 302  1h;
  25.                 proxy_cache_valid  404      1m;
  26.                 proxy_redirect https://www.google.com/ /;
  27.                 proxy_cookie_domain google.com webres.wang;
  28.                 proxy_pass              http://google;
  29.                 proxy_set_header Host "www.google.com";
  30.                 proxy_set_header Accept-Encoding "";
  31.                 proxy_set_header User-Agent $http_user_agent;
  32.                 proxy_set_header Accept-Language "zh-CN";
  33.                 proxy_set_header Cookie "PREF=ID=047808f19f6de346:U=0f62f33dd8549d11:FF=2:LD=zh-CN:NW=1:TM=1325338577:LM=1332142444:GM=1:SG=2:S=rE0SyJh2w1IQ-Maw";             
  34.                 sub_filter www.google.com devops.webres.wang;
  35.                 sub_filter_once off;
  36. }
  37. }

解释下吧:

  • 1、这里监听了80和443端口,用了ssl加密,高大上。ssl证书是免费的,startssl,自己去申请个吧。
  • 2、定义了个upstream google,放了5个谷歌的ip,如果不这样做,就等着被谷歌的验证码搞崩溃吧。
  • 3、也设置了反向代理缓存,某些资源不用重复去请求谷歌获取,加快搜索速度。
  • 4、proxy_redirect https://www.google.com/ /; 这行的作用是把谷歌服务器返回的302响应头里的域名替换成我们的,不然浏览器还是会直接请求www.google.com,那样反向代理就失效了。
  • 5、proxy_cookie_domain google.com webres.wang; 把cookie的作用域替换成我们的域名。
  • 6、proxy_pass http://google; 反向代理到upstream google,会随机把请求分配到那几个ip。忘记说了,那几个ip可以在自己的vps或服务器上使用nslookup www.google.com获取。
  • 7、proxy_set_header Accept-Encoding “”; 防止谷歌返回压缩的内容,因为压缩的内容我们无法作域名替换。
  • 8、proxy_set_header Accept-Language “zh-CN”;设置语言为中文
  • 9、proxy_set_header Cookie “PREF=ID=047808f19f6de346:U=0f62f33dd8549d11:FF=2:LD=zh-CN:NW=1:TM=1325338577:LM=1332142444:GM=1:SG=2:S=rE0SyJh2w1IQ-Maw”; 这行很关键,传固定的cookie给谷歌,是为了禁止即时搜索,因为开启即时搜索无法替换内容。还有设置为新窗口打开网站,这个符合我们打开链接的习惯。
  • 10、sub_filter www.google.com devops.webres.wang;当然是把谷歌的域名替换成我们的了,注意需要安装nginx的sub_filter模块

好了,说明够详细了,祝各位享受到高质量的谷歌搜索。