规范的意义
- 没有规矩,不成方圆。 这话应该都不陌生,分析我们以往在服务器使用方面的情况,普遍的现象是大家对服务器 的使用随意性很大,没有一个规范进行指导和约束,管理员和开发人员基本可以随意配置 使用服务器,因此造成了很多问题:
- 系统维护管理的难度和成本越来越大
- 服务器配置无法统一,开发环境配置无法统一
- 系统部在完成服务器的基本安装后,交由应用部门使用的过程完全不受控制
- 开发人员随意配置服务器开发环境,造成安全隐患,增加系统维护管理的难度和成本
- 由于开发环境不统一,因此为程序开发和移植、安装等工作增加了不必要的麻烦
- 由于开发环境不统一,也增加了开发人员熟悉服务器环境甚至重新配置服务器的麻烦 因此我们希望可以由系统部牵头,和广大的开发人员讨论,制定并逐步完善一个比较 通用的适应大多数开发需求的开发环境配置规范,由系统部在完成系统基本安装后, 按照规范完成开发环境的安装和配置,争取交给应用部门的服务器就是可以直接使用 的,不必要重新配置的。 由于是初稿,规范未必合理,但是有规范总比没有规范好,我们可以经过实践和讨论 不断完善规范。
目录布局和文件命名规范
- 目录命名主要是为了统一维护方便,也为了方便使用,可以通过下面的几个方法 达到统一目录布局和查找的目的:
- mount 直接创建相应的 mount 加载点如 /sinasrv/www
- mount --bind 参数,通过这个方法可以把一个目录挂载到另一个目录下,例如:
- mount --bind /sinasrv/www/htdocs /data1/apache/htdocs mount --bind /sinasrv/www/logs /data2/apache/logs mount --bind /sinasrv/www/mmcache /data2/mmcache
- 符号链接 (这个最常用)
常用目录布局规范
- 明确划分目录的好处是我们可以给不同类型使用的目录配置不同的访问权限, 已此来达到较高的安全控制。
- 软件安装根目录
- /usr/local/sinasrv
- Apache 安装目录
- /usr/local/sinasrv/apache
- MySQL 安装目录
- /usr/local/sinasrv/mysql
- 数据根目录命名
- /sinasrv
- Apache 数据根目录
- /sinasrv/www
- MySQL 数据根目录
- 数据根目录前缀 + "mysql"应用类别目录名 /sinasrv/mysql
- Apache 虚拟主机的文档、程序、数据的目录命名
- Apache 文件目录
- 根目录 + 文档目录 + 虚拟主机域名 /sinasrv/www/htdocs/survey.news.sina.com.cn
- Apache cgi 程序的目录
- 根目录 + 文档目录 + 虚拟主机域名 /sinasrv/www/cgi-bin/survey.news.sina.com.cn
- Apache 程序数据目录
- 根目录 + 数据目录 + 虚拟主机域名 /sinasrv/www/data/survey.news.sina.com.cn
- Apache 程序缓存目录
- 根目录 + 缓存目录 + 虚拟主机名 /sinasrv/www/cache/survey.news.sina.com.cn
- Apache 基于 nfs 的共享数据目录
- /sinasrv/www/ndata/survey.news.sina.com.cn
- Apache 基于 nfs 的共享缓存目录
- /sinasrv/www/ncache/survey.news.sina.com.cn
- Apache 基于 nfs 的共享文档目录
- /sinasrv/www/nhtdocs/survey.news.sina.com.cn
- Apache 文件目录
- Turck MMCache 的程序缓存目录
- /sinasrv/www/mmcache
- PHP Session 的目录
- /sinasrv/www/phpsession
- 用户文件上传目录
- /sinasrv/www/userupload
- MySQL 数据目录命名
- MySQL 数据根目录 + "mysql" + 开放端口号 /sinasrv/mysql/mysql3310
说明:上面关于虚拟主机的配置可以看到,虚拟主机使用的各个特定需求的目录 都是定义在每个特定目录下的,比如data,是所有虚拟主机的data目录的跟, 每个虚拟机主机已域名创建自己的目录。这样做的好处是可以统一控制data的权限 而不用把data目录创建在每个虚拟机主机的根目录下。
常用文件命名规范
- Apache 虚拟主机的日志目录和日志文件命名
- 日志根目录
- /sinasrv/www/logs
- 错误日志
- 日志根目录 + 错误日志目录 + 虚拟主机域名 + "-error_log"后缀 /sinasrv/www/logs/error/survey.news.sina.com.cn-error_log
- 访问日志
- 日志根目录 + 错误日志目录 + 虚拟主机域名 + "-access_log"后缀 /sinasrv/www/logs/access/survey.news.sina.com.cn-access_log
- 归档日志
- 日志根目录 + 归档日志目录 + 日期目录 + 虚拟主机域名 + 外网IP地址 + "_cn"后缀 /sinasrv/www/logs/archive/051231/survey.news.sina.com.cn_10.44.6.24_cn.gz
- 日志根目录
- MySQL 配置文件命名
- MySQL 数据目录名 + "my" + 开放端口号 + ".cnf /sinasrv/mysql/mysql3310/my3310.cnf
- MySQL socket文件命名
- /tmp目录名 + "mysql" + 端口号 + ".sock" /tmp/mysql3310.sock
- rsync 配置文件
- /etc/rsyncd.conf
- rsync 的验证配置文件
- /etc/rsyncd.secrets
其他命名规范
- MySQL 的库命名规范
- 使用域名或者项目名称 比如域名为:news.survey.sina.com.cn,那么库命名为:news_survey 比如项目名称为:通用测试项目,那么库命名为:generaltest
- MySQL 读写帐户命名规范
- 默认只配置一个和库同名的帐户,具有该数据库的全部操作权限。
- MySQL 只读帐户命名规范
- 默认只配置一个只读帐户,可以访问该数据库的全部数据,命名为: 库名 + "_r" 后缀
- MySQL server-id 命名规范
- 使用所在服务器的外网IP地址后两位 + MySQL监听端口号, IP地址不足3位补0, 例如:10.44.6.17,端口为 3306,那么 server-id = 0060173306
- rsync 模块名
- 默认使用虚拟主机的域名为模块名。 如: news.survey.sina.com.cn
本地磁盘使用和目录命名
- 假设都为3块硬盘的服务器,系统盘不用来保存数据,第一块数据库盘加载在/data1
- 目录下,第二块数据盘加载在/data2目录下。
- /data1 磁盘创建如下目录:
- /data1/sinasrv/www/htdocs
- /data1/sinasrv/www/data
- /data1/sinasrv/www/cgi-bin
- /data1/sinasrv/mysql/
- /data2 磁盘创建如下目录
- /data2/sinasrv/www/logs
- /data2/sinasrv/www/cache
- /data2/sinasrv/www/mmcache
- /data2/sinasrv/www/phpsession
- /data2/sinasrv/www/userupload
- /data2/sinasrv/mysql/
- 对于1块数据盘的服务器,将数据盘加载在 /data1 目录下,所有的目录都创建在
- /data1/sinasrv 目录下。
- 对于3块数据盘的服务器,将第三块数据盘加载在 /data3 目录下,
- 创建 /data3/sinasrv 目录,以后根据需要再使用。
- 上面的各个目录通过符号链接到 /sinasrv/www 相应目录下,如果在 chroot 环境下,
- 则通过 mount --bind 加载到 /sinasrv/www 目录下。
实现兼容性的目录命名
- 通过符号链接或者 mount --bind 方法实现一些习惯使用的固定目录。
- 符号链接 /usr/local/apache 到 /usr/local/sinasrv/apache
- 符号链接 /data1/apache/htdocs 到 /sinasrv/www/htdocs
- 符号链接 /usr/local/mysql 到 /usr/local/sinasrv/mysql
- 符号链接 /data2/mysql 到 /usr/local/sinasrv/mysql
软件安装目录布局规范
软件包安装时的目录布局
- 该规范适用于大多的基础开发库软件和一些工具软件
- 例如 libiconv, libpng, zlib
- 例如 stow, php, perl
- 软件根目录和子目录布局
- --prefix = /usr/local/sinasrv
- --exec_prefix = %{_prefix}
- --bindir = %{_exec_prefix}/bin
- --sbindir = %{_exec_prefix}/sbin
- --libexecdir = %{_exec_prefix}/libexec
- --datadir = %{_prefix}/share
- --sysconfdir = %{_prefix}/etc
- --sharedstatedir= %{_prefix}/com
- --localstatedir = %{_prefix}/var
- --lib = lib
- --libdir = %{_exec_prefix}/%{_lib}
- --includedir = %{_prefix}/include
- --oldincludedir = /usr/include
- --infodir = %{_prefix}/info
- --mandir = %{_prefix}/man
- Apache 软件安装目录
- --prefix = /usr/local/sinasrv/apache
- MySQL 软件安装目录
- --prefix = /usr/local/sinasrv/mysql
软件安装编译规范
Apache 软件的编译规范
- 各个模块都采用 DSO 方式编译,启动时只选择常用的模块,如下:
-
http_core.c mod_log_config.c mod_mime.c mod_include.c mod_dir.c mod_cgi.c mod_alias.c mod_rewrite.c mod_access.c mod_auth.c mod_so.c mod_env.c mod_negotiation.c mod_setenvif.c mod_php4.c
-
PHP 软件的编译规范
- 采用 DSO 模式编译为 Apache 动态加载模块,需要先安装 Apache.
- 扩展模块以 DSO 方式编译安装,启动时只加载需要使用的模块,
-
ctype gd iconv mysql overload pcre posix session sina standard tokenizer Turck MMCache xml
-
服务器配置文件规范
Apache 默认配置说明
- Apache
- httpd.conf 配置文件主要的配置如下:
- 基本配置如下:
ServerType standalone ServerRoot "/usr/local/sinasrv/apache" PidFile /sinasrv/www/logs/httpd.pid ScoreBoardFile /sinasrv/www/logs/httpd.scoreboard Timeout 120 KeepAlive On MaxKeepAliveRequests 10240 KeepAliveTimeout 10 MinSpareServers 15 MaxSpareServers 30 StartServers 15 MaxClients 1024 MaxRequestsPerChild 0 Port 80 User www Group www ServerAdmin tongjian@staff.sina.com.cn ServerName 127.0.0.1 DocumentRoot "/sinasrv/www/htdocs/default" <Directory /> Options FollowSymLinks AllowOverride None </Directory> LogFormat "%h %l %u %t %T \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined CustomLog /sinasrv/www/logs/access_log combined ServerSignature Off ServerTokens ProductOnly DirectoryIndex index.shtml index.html index.php AccessFileName .htaccess <Files ~ "^\.ht"> Order allow,deny Deny from all Satisfy All </Files> UseCanonicalName On HostnameLookups Off <IfModule mod_setenvif.c> SetEnvIfNoCase Request_URI "\.(gif|js|jpg|swf)$" dontlog </IfModule> <FilesMatch "\.(sh|log|txt|sql|bak|bak2|old|1|2|php~)$"> Deny from all </FilesMatch> ErrorDocument 404 "Hi, The requested URL was not found on this server !" ErrorDocument 500 "Ooooooooooooops, I don't know what's happen !" NameVirtualHost *:80
- 基本配置如下:
- 虚拟主机配置格式如下
-
<VirtualHost *:80> ServerName news.survey.sina.com.cn ServerAdmin minghui@staff.sina.com.cn DocumentRoot /sinasrv/www/htdocs/news.survey.sina.com.cn/ ErrorLog /sinasrv/www/htdocs/error/news.survey.sina.com.cn-error_log CustomLog /sinasrv/www/htdocs/error/news.survey.sina.com.cn-access_log combined env=!dontlog Alias "/data/" "/sinasrv/www/data/news.survey.sina.com.cn/" Alias "/cache/" "/sinasrv/www/cache/news.survey.sina.com.cn/" SetEnv SINASRV_DATA_DIR "/sinasrv/www/data/news.survey.sina.com.cn/" SetEnv SINASRV_CACHE_DIR "/sinasrv/www/cache/news.survey.sina.com.cn/" SetEnv SINASRV_NFSDATA_DIR "/sinasrv/www/nfsdata/news.survey.sina.com.cn/" SetEnv SINASRV_NFSCACHE_DIR "/sinasrv/www/nfscache/news.survey.sina.com.cn/" SetEnv SINASRV_NFSHTDOCS_DIR "/sinasrv/www/nfshtdocs/news.survey.sina.com.cn/" </VirtualHost>
-
PHP 默认配置说明
- php 使用 php.ini-recommended 作为模板配置文件,在此基础之上增加一些安全
- 方面的设置。
- 下面是对部分配置的说明
-
- output_buffering = 4096 性能调节参数,默认是关闭的。 - variables_order = "GPC" 性能调节参数,去掉了不常用的环境变量, 只用Get,POST,Cookie,如果访问环境变量可以考虑调用getenv() 目前的配置是 "GPCS",不知道可不可以去掉 Server环境变量? - error_reporting = E_ALL 安全因素 - allow_call_time_pass_reference = Off 代码清洁 - expose_php = Off 安全因素 - register_argc_argv = off 命令行参数,在CLI SAPI方式中才有用 - magic_quotes_gpc = off 关闭系统自动escape用户输入, 用户可以根据需要使用下列函数自己进行escape: addslashes(), escapeshellcmd(), mysql_escape_string() - allow_persistent = On 目前全部开放,考虑到个别程序的错误会引起MySQL的不稳定,以后可能会给个 别vhost开放这个特性,也可能会在mysql数据库中限制最大连接数或者设置 timeout,或者设置php中的关于database的max_links and max_persistent - safe_mode, open_basedir and memory_limit 处于性能考虑,不推荐使用上面的指令,the checks performed by PHP to enforce them are quite expensive and can lead to significant performance losses if enabled. - display_errors Off 生产环境关闭错误显示
-
MySQL 默认配置说明
- MySQL 默认使用 my-large.cnf 作为配置文件,在此基础之上根据一些实际的环境
- 需求进行特定性的优化配置。
- 下面是一些主要的配置:
-
[mysqld] datadir = /data2/mysql3308 port = 3308 socket = /tmp/mysql3308.sock skip-locking key_buffer = 256M max_allowed_packet = 1M table_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M myisam_sort_buffer_size = 64M thread_cache = 16 query_cache_size = 16M thread_concurrency = 4 max_connections = 512 max_user_connections = 128 wait_timeout = 60 long_query_time = 1 server-id = 0060173308 log-bin
-
日志文件管理说明
Apache 访问日志
- Apache access_log 文件默认不记录图片访问记录。
- Apache access_log 每日临晨0点自动归档,每日生成一个日志文件,按日期保存
- 在日志归档目录下,自动压缩成 gzip 格式。
- Apache error_log 日志文件不归档,每日临晨0点自动清空。
- 默认访问日志只保存在本地服务器,存留期为30天,超出后自动删除。
MySQL 访问日志
- MySQL 打开 --log-slow-queries 选择用来记录较慢的查许,方便程序性能分析和监控。
- 设置 long_query_time = 1 ,记录查询时间超出 1 秒的访问。
其他有待解决的问题
- 目前希望设置为 可执行的目录不能写,可写的目录不能执行,但是如果可写的目录下的
- 文件被渗透,包含有恶意的或者造成XSS的 javascript 代码,那么理论上还是会存在 威胁,比如用户的 session 信息,或者用户名、密码暂存在 cookie 中的话,那么 仍然存在威胁,因此要考虑用户的cookie中尽量不要包含敏感数据,比如是否可以做到 只包含一个用户的 SessionID
- 由于在安全模式下设置 include_path 比较麻烦,可能在符号链接中不能生效,或者
- php.ini 文件没有包含的路径,在 httpd.conf 包含了也不能用,因此可能不考虑使用 符号链接的方式将 htdocs 目录下不存在的 data, cache 目录链接在 htdocs 目录下, 因为有时得考虑 data, cache 目录下的文件是具有执行权限的。
- 关于多虚拟主机的 web 站点中各虚拟主机的 htdocs 目录的保护问题。
- 似乎必须要做保护,要做到各个 vhost 之间不能通过 web 相互浏览彼此的目录,默认 不作任何配置是可以相互浏览的。目前知道的可以做到这个限制的方法是在 php 环境 下,php 有一个叫做 open_basedir 的指令,可以在 httpd.conf 的vhost中设置, 这样可以做到在 php 下每个 vhost 之间不能浏览文件
- 关于 include_path 的限制问题
- 前面提到过,我们希望把 web 的目录划分成几个类别,可执行的目录不可写, 可写的目录不可执行,如果可以这样的话就不用考虑 include_path 的问题。 如果不行,那么就会面临这样一个问题。 比如 htdocs 是可以执行的,data, cache 目录是可写的,也可以执行,但 它不再 htdocs 的目录下,是另外一个目录的子目录,但是有符号链接在 htdocs 中,那么如果 data, cache 下的程序需要包含 (include) htdocs 下的文件时, 我们设置了 include_path = ".:/usr/local/sinasrv/lib/php/" 将导致data, cache下的程序不能够包含,将会被拒绝。即使设置如下的方式, 在安全模式下也不可以。 include_path = ".:/usr/local/sinasrv/lib/php/:../include:../../include:../../../include"
- 关于运行多个站点的 apache 服务器环境的安全问题
- 前面提到过,关于多个虚拟站点之间默认可以浏览彼此文件的安全隐患, 这里主要是记录一下相关的解决思路。
- suexec 模式可以解决 cgi 方式运行的问题,可以参考如下资料
- 可以考虑在配置好的虚拟站点中放置一个统一命名的虚拟站点配置文件。
- 比如在 /include/siteconfig.inc 还可以结合 apache 的 setenv 功能直接设置好虚拟站点的配置信息。