Web环境搭建记录
安装Apache
1 | apt-get install apache2 |
在浏览器中访问127.0.0.1
,出现如下页面则代表安装成功
安装MySQL
安装MySQL服务端
1 | apt-get install mysql-server |
安装MySQL客户端
1 | apt-get install mysql-client |
以root用户身份登录MySQL
1 | mysql -u root |
为root用户设置密码’123456’
1 | ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; |
退出MySQL
1 | mysql> quit |
后续再登录MySQL需使用刚才设置的密码
1 | mysql -u root -p |
安装PHP
1 | apt-get install php |
如此会安装最新版本的php
在 /var/www/html
下新建一个phpinfo.php
文件
1 | vim /var/www/html/phpinfo.php |
编辑如下内容:
1 |
|
在浏览器中访问此文件,若能够看到PHP相关信息说明PHP安装成功且PHP代码能在此环境运行
到此,LAMP环境算是初步部署好了。下面,简要记录下Nginx的安装,PHP连接MySQL的操作,以及一些简单加固技术。
安装Nginx
Nginx与Apache都能提供Web服务,两者区别见 浅析Nginx与Apache的区别
有一点要说明的是,Apache对PHP支持比较简单,但Nginx本身不会对php文件进行解析,需要配合php-fpm(第三方的fastcgi进程管理器)才能实现对PHP的解析支持。
关于这一点详情可见 Nginx工作原理和优化总结
注意,如果Apache服务已经开启,在使用Nginx前需手动关闭Apache服务
1 | service apache2 stop |
安装Nginx
1 | apt-get install nginx |
如果之前没有安装过Apache,直接在浏览器中访问127.0.0.1
,出现如下页面则代表nginx安装成功。若已安装过Apache,则访问127.0.0.1/index.nginx-debian.html
但此时还无法运行php代码,如无法访问phpinfo页面,还需安装php-fpm,注意根据php版本安装对应的php-fpm
1 | apt-get install php8.0-fpm |
以及修改nginx配置文件
1 | vim /etc/nginx/sites-available/default |
:wq
,保存退出后重启nginx服务,使修改过的配置信息生效
1 | service nginx restart |
然后和上面一样,成功访问127.0.0.1/phpinfo.php
则说明nginx已经能够支持PHP
PHP连接MySQL
方式:通过MySQLi扩展
安装mysqli扩展
1 | apt-get install php8.0-mysqli |
在 /var/www/html/
目录下创建connect.php
,编辑内容如下:
1 |
|
访问127.0.0.1/connect.php
,页面上即出现“数据库连接成功!”,并执行mysql语句,返回了查询的数据。
安全加固
加固Linux系统
远程登陆
在使用和管理服务器时,往往我们需要远程登陆服务器,这就需要我们保证远程登陆过程的安全性。以下方法可以一定程度提高远程登陆的安全性。
- 强制使用高强度用户密码(数字、字母、字符的组合且长度14位以上)
- 更改 SSH 默认的端口(22)为随机端口
- 禁止 root 身份的远程登陆
- 使用公钥认证机制进行远程登陆
现以 Ubuntu 系统为例,完成上述操作:
要强制用户使用高强度密码,需要安装额外的模块 libpam-cracklib
1 | apt-get install libpam-cracklib |
在 Ubuntu 中,密码策略(规定密码的长度,字符等)定义在 /etc/pam.d/common-password
文件中
如果要规定密码长度为 14,包含大小写字符数字和字符,可以在 pam_unix.so
的前一行,添加:
1 | password required pam_cracklib.so try_first_pass retry=3 minlen=14 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 difok=2 reject_username |
上述配置的选项的描述如下,详情参考 libpam-cracklib 文档:
选项 | 描述 |
---|---|
retry=N | 设置密码时的,最大重试次数 |
minlen=N | 新密码的最小长度 |
lcredit=N | 最少小写字母数,小于0,正常计算 minlen,大于0,计算 minlen 额外加 1 |
ucredt=N | 最少大写字母数,小于0,正常计算 minlen,大于0,计算 minlen 额外加 1 |
dcredit=N | 最少数字的数,小于0,正常计算 minlen,大于0,计算 minlen 额外加 1 |
ocredit=N | 最少其它字符数,小于0,正常计算 minlen,大于0,计算 minlen 额外加 1 |
difok=N | 和旧密码不同的字符数 |
reject_username | 禁止用户名作为密码 |
更改ssh默认端口,禁止root身份登录:
修改 ssh的配置文件 /etc/ssh/ssh_config
找到 # Port 22
把22更改为其他端口号
找到 #PermitRootLogin
,更改为:
1 | PermitRootLogin no |
保存后重启ssh服务,下次远程登陆时则需要指定该端口进行登陆,而且无法使用 root 用户登陆
1 | ssh username@ip-addr -p portnum |
使用公钥认证机制进行远程登陆:
SSH 登陆 提供公钥认证机制的登陆,即不需要密码的登陆方式,但是需要在客户端生成公钥和私钥,并将公钥发送给服务端,服务端将公钥添加到相应用户的配置文件中。
首先客户端需要生成密钥对:
1 | ssh-keygen -t rsa -b 4096 |
使用默认文件名,一路 Enter 到底,生成的密钥对文件在 ~/.ssh/
目录下,其中 id_rsa
为私钥,id_rsa.pub
为公钥。
接着将公钥文件上传到服务器:
1 | ssh-copy-id username@ip-addr -p portnum |
该命令会把公钥文件的内容,写入到 /home/username/ssh/authorized_keys
文件中,也可以手动添加内容。如此一来就可以直接以 username
的身份,而不用使用密码登陆服务器了。
加固Apache
禁止访问外部文件
禁止 Apache 访问 Web 目录之外的任何文件,修改 httpd.conf 配置文件,其中 /web 为网站根目录。
1 | Order Allow,Deny |
禁止目录列出
目录列出会导致明显信息泄露或下载,可修改 httpd.conf 配置文件:
将Options Indexes FollowSymLinks中的Indexes去掉,就可以禁止 Apache 显示该目录结构。Indexes的作用就是当该目录下没有 index.html 文件时,自动显示目录结构。
隐藏版本信息
隐藏 Apache 的版本号及其它敏感信息。修改 httpd.conf 配置文件:
1 | ServerSignature Off ServerTokens Prod |
限制HTTP请求方法
禁用 PUT、DELETE 等危险的 HTTP 方法。
修改 httpd.conf 配置文件,只允许 get、post 方法。
1 | <Location /> |
加固Nginx
隐藏版本信息
Nginx 默认开启 Server Token(显示版本号),这样使得 Nginx 的版本号很容易被获取,如下图为访问域名不存在资源时的返回页面,可以看到 Nginx 的版本号
在配置文件 /etc/nginx/nginx.conf
中 http 块中添加,保存并重启nginx服务。
1 | server_tokens off |
关闭后,访问域名下不存在的资源,返回页面中没有了 Nginx 的版本信息。
限制访问敏感资源
有些资源我们可能不想对外开放,比如一些版本控制的备份文件,如.git/.svn等,这些暴露了可能会将整个项目的结构或是源代码都泄露了,可通过如下设置限制对其的访问
1 | location /test/ { |
限制HTTP请求方法
编辑配置文件,添加如下内容:
1 | if ($request_method !~ ^(GET|HEAD|POST)$ ) { |
保存并重启nginx服务(只允许常用的GET和POST方法,顶多再加一个HEAD方法)
限制IP访问
编辑配置文件,在server标签内添加如下内容:
1 | location / { |
加固MySQL
运行 mysql_secure_installation
工具(安装 mysql 后自带的 shell 脚本),进行 mysql 的安全检查,
根据提示,设置密码为最高级别,并为 root 用户设置密码,最后同意以下选项:
- Remove anonymous users? – 删除匿名用户
- Disallow root login remotely? – 禁止远程使用 root 用户登陆
- Remove test database and access to it? – 删除测试数据库和其访问权限
- Reload privilege tables now? – 重载授权表
加固PHP
当文件不存在时停止 PHP 处理
Nginx 对于 PHP 的默认配置使得 PHP 解释器接受所有以 .php
结尾的 URI,这样一来就会存在很大的风险,存在任意代码执行漏洞,具体解释见Passing Uncontrolled Requests to PHP
修改 /etc/php/7.4/fpm/php.ini
文件(不同系统该文件位置略有不同),设置cgi.fix_pathinfo=0
,可以禁止 PHP 解释器查找文件系统中不存在的文件。
禁用危险的 PHP 函数
当以下函数不使用时,可修改 php.ini
以禁用:
1 | disable_functions =exec,eval,phpinfo,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source |
限制文件上传功能
如果网站不需要文件上传功能,应该禁用,修改php.ini
。
1 | file_uploads=Off |
如果需要上传功能,则设置上传文件的大小,根据实际情况设置,如头像图片上传1M足矣,修改php.ini
。
1 | file_uploads=On |
设置 POST 方法传输数据的大小
POST 方法是当客户端需要向服务器发送数据时使用的,该方法可被用于对服务器进行 Dos 攻击等,所以需要将其能传输的数据大小设置成合理的数值,如果网站不需要上传文件等数据量大的操作,4KB也应该足够了。
1 | post_max_size=1K |
防止 PHP 版本信息泄露
1 | expose_php = Off |
限制 PHP 脚本的最长执行时间
1 | # set in seconds |
这样可以有效防止大规模的 DOS 攻击。
关闭错误信息提示
一般 PHP 环境在没有连接到数据库或者其他情况下会有错误提示信息,错误信息中可能包含 PHP 脚本当前的路径信息或者查询的 SQL 语句等信息,这类信息如果暴露给黑客是不安全的,因此建议禁止该错误提示:
1 | display_errors = Off |
如果确实要显示错误信息,一定要设置显示错误信息的级别。例如,只显示警告以上的错误信息:
1 | error_reporting = E_WARNING & E_ERROR |