sudo在rc.local中无法运行

原因是sudo会检查是否是在tty中,系统启动的时候,不属于tty环境,因此无法执行

解决方法,命令行执行visudo,找到Defaults    requiretty并注释掉!

简单谈谈怎么提高Linux服务器的安全性

网络攻击无处不在,这个要记好!

(一)防备外部网络入侵
1)不要安装或关闭不使用的服务;
2)不安全的服务用安全的服务替代,比如可以用ssh自带的sftp替代传统的ftp;
3)必备的服务如果只是本机用务必只绑定到127.0.0.1;
4)可以限定使用ip范围的,使用服务自身机制、pam机制或iptables有限开放;当然像http 80/443这样提供公开服务的,一般不需要限制,但是可以通过日志分析危险的ip做限制,阻止ddos、cc攻击;
4)不是提供公开服务的,可以修改默认端口,自己使用或者使用范围有限的服务,例如ssh、ftp;
5)必要的版本升级,消除程序自身bug

(二)帐号管理
1)只开放需要的帐号;
2)设置一个强有力的密码,例如hjU7MwnY06,甚至2kcPu6wEQChbsfqN,这样的密码除了自己泄露之外,暴力破解的可能能有多大?
3)对外的服务只开放必要的帐号;

tip:这样的密码太难记?我推荐用KeePass来管理,开源、支持很多平台、密码文件通用、安全!

(三)日常检查
经常检查日志,测试设置的限制,发现问题及时修改配置或使用服务自身机制、pam机制或iptables封堵恶意ip!

使用RSA密钥进行免密码SSH远程登录

一般SSH是通过帐号和密码进行远程登录,SSH同时也提供了基于RSA密钥的验证方式,可以不用输入密码。

假设要从HostA机中UserA远程登录HostB机的用户UserB:
1、HostA中UserA操作
#生成密钥,要求输入的密码可以留空,私钥位于~/.ssh/id_dsa,公钥位于~/.ssh/id_dsa.pub
ssh-keygen -t dsa

2、HostB中UserB操作
将刚才生成的id_dsa.pub复制成HostB机UserB目录下的~/.ssh/authorized_keys即可

3、现在在HostA中执行SSH登录就可以直接登录而不需要输入密码了
ssh UserB@HostB


很简单!

如何在linux下使用iptables进行远程端口转发

这里特别指出的是远程端口转发,而不是内外网端口映射,意思是:公网上两台机器,利用HostA(IpA)的PortA端口映射到远程HostB(IpB)的PortB端口;用户虽然访问的是IpA的PortA端口,但实际最终连接到的是IpB的PortB端口。

前提是已经安装了iptables,再以root身份运行以下配置,如果重启了机器,需要重新执行,可以写到启动脚本文件中去。

[quote]#将访问目的地址为IpA:PostA的数据包转换为访问目的地址为IpB:PortB,建立转发的正向数据通道
iptables -t nat -I PREROUTING -p tcp --dport PortA -j DNAT --to IpB:PortB

#将访问目的地址为IpB:PortB的数据包中客户端Client的原始地址动态转换为HostA的地址IpA,建立转发的反向数据通道;尝试过用SNAT题替代,但是未成功,不知道是写的规则不对还是怎么的。我觉得MASQUERADE要比SNAT多一些处理,应该是维护了一张返回通道的转发对应表,类似我们常用NAT网关
iptables -t nat -I POSTROUTING -p tcp -d IpB --dport PortB -j MASQUERADE

/etc/rc.d/iptables save #保存
/etc/rc.d/iptables restart #重启iptables服务,否则不生效
echo 1 > /proc/sys/net/ipv4/ip_forward #重启iptables后,ip_forward会变回0,需要重新设置
[/quote]


example
阅读全部

如何在Nginx中搭建HTTPS站点

这里采取的是在StartSSL申请免费证书,使用Nginx + php-cgi(php-fpm)的方式建立HTTPS加密的站点。

首先在StartSSL注册,点左上角图标“Sign-up For Free”,注册的过程要填写比较详细的地址、电话什么的,否则可能被拒,具体注册教程可以Google一下,很多介绍,也很简单。注册过程要验证邮件地址,注册成功之后会自动安装一个StartCom Free Certificate Member的证书,这个就是用来登录的,搞证书的完整登录用证书也算是门当户对。必须用IE浏览器注册,因为要装ActiveX控件。


注册之后,点击Authenticate,再进入Control Panel,  先使用Validations Wizard验证域名,再使用Certificates Wizard创建证书,类型为“Web Server SSL /TLS Certificate”。在接下来的步骤里面,可以在线创建私钥,但我发现在网站上直接输入密码,提交会有一个JavaScript错误,导致无法继续,换了浏览器和机器也是一样。

所以我们可以选择创建私钥的步骤Skip,然后把自己采用自己创建的CSR用用本工具打开,粘贴到下一步“Submit Certificate Request (CSR)”的文本框中;下面用到的openssl是OpenSSL库里面的一个工具。
1)创建一个4096长度的私钥
openssl genrsa -des3 -out server.key 4096

2)创建一个CSR (Certificate Signing Request)
openssl req -new -key server.key -out server.csr
其中challenge password为空

这样就可以得到一个CRT证书文件,将其从页面中粘贴到本地一个文本文件,并改名为CRT后缀即可。今后要可以在Control Panel -> Tool Box ->Retrieve Certificate重新获得。


Nginx配置很简单,最重要的配置红色标识。一些PHP程序可能会使用_SERVER["HTTPS"]参数来判断当前是HTTPS还是HTTP,这个会影响程序生成的一些链接的前缀,如果检测不正确,可能会导致访问HTTPS站点时候,浏览器提示“本页不但包含安全的内容,也包含不安全的内容。是否显示不安全的内容”,而由于是采用反向代理的方式,透过Nginx访问php-cgi,而php-cgi不是以HTTPS方式运行的,所以必须要显示的制定生成参数fastcgi_param HTTPS on; 

server
{
    listen a.b.c.d:443;

    access_log /xxx/ssl.access.log main;
    error_log  /xxx/ssl.error.log;


    root /xxx/;
    index index.php index.html index.htm;


    ssl on;
    ssl_certificate /xxx/server.crt;
    ssl_certificate_key /xxx/server.key;

    ssl_session_timeout 5m;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers on;


    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        fastcgi_param HTTPS on; 
        include fastcgi_params;
    }


    location ~ /\.ht {
        deny all;
    }

}


启动试一试应该就可以了,但每次启动Nginx的时候都会提示输入私钥密码,这个可以这样解决:
1) 去除密码
openssl rsa -in server.key -out server.nopass.key

2)把Nginx的配置替换为
ssl_certificate_key /xxx/server.nopass.key;即可


经过测试,在IE 7.0.5730.11、Chrome 4.1.249.1064版本中使用正常;在Firefox 3.5.3会提示“此连接是不受信任的”,这是因为StartSSL的根证书还没有被FF认可,只是被M$和Google认可,添加个例外就可以继续访问了,加密功能是一样的,不过变得和自己的做的证书一样了。免费的不求太完美,将就用。

如何在BIND9中彻底禁用递归,限制只解析本机域名

作为域名NS记录指向的DNS服务器,不同于开放给公众的DNS服务器,不需要提供本机配置域名之外的域名解析。当DNS解析的域名本机中没有的时候,就会发起递归(recursion)或者转发(forward)到远程DNS去查询。

递归:本机直接从根服务器上寻找对应域名的NS记录,再由本机到NS指向的服务器中查询记录
转发:本机将解析请求转发到指定的服务器去解析,将转发服务器的响应结果直接反馈给查询者

BIND9默认打开递归查询和关闭转发功能,如何彻底关闭递归,就成了主要问题,设置中还发现一些有趣的问题。

测试平台:Debian 5.0.4
BIND9版本:BIND 9.5.1.dfsg.P3-1+lenny1

配置文件:/etc/bind/named.conf.options
1、只设置“recursion no;”
C:\>nslookup
> server 192.168.99.104
> www.google.com
Server: [192.168.99.104]
Address: 192.168.99.104

Name: www.google.com
Served by:
- K.ROOT-SERVERS.NET
- I.ROOT-SERVERS.NET
- L.ROOT-SERVERS.NET
- B.ROOT-SERVERS.NET
- M.ROOT-SERVERS.NET
- G.ROOT-SERVERS.NET
- F.ROOT-SERVERS.NET
- A.ROOT-SERVERS.NET
- J.ROOT-SERVERS.NET
- C.ROOT-SERVERS.NET


服务器虽然没有进行递归查询,但是还是响应了客户端根服务器的地址。如何彻底关闭呢,这个问题折腾了很久,未果。BIND9的文档(http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html)中有这样的描述:

recursion
If yes, and a DNS query requests recursion, then the server will attempt to do all the work required to answer the query. If recursion is off and the server does not already know the answer, it will return a referral response. The default is yes. Note that setting recursion no does not prevent clients from getting data from the server's cache; it only prevents new data from being cached as an effect of client queries. Caching may still occur as an effect the server's internal operation, such as NOTIFY address lookups. See also fetch-glue above.

allow-recursion
Specifies which hosts are allowed to make recursive queries through this server. If not specified, the default is to allow recursive queries from all hosts.
Note that disallowing recursive queries for a host does not prevent the host from retrieving data that is already in the server's cache.

可问题是,这个cache如何关闭呢?文档里没有详细描述,找了很久,发现个配置allow-query-cache,这个似乎在官方的文档中没有呢?


2、同时设置“recursion no;”和"allow-query-cache { none; };"
C:\>nslookup
> server 192.168.99.104
> www.google.com
Server: [192.168.99.104]
Address: 192.168.99.104

*** [192.168.99.104] can't find www.google.com: Query refused

彻底关闭了递归查询,拒绝响应,达到目的。


3、只设置"allow-recursion { none; };"
测试结果同2

这是在后来改配置的时候偶尔发现的,allow-recursion貌似不需要关闭cache。一直认为allow-recursion和recursion是完全一样的,看来不是这样。当然,这个也许是我的测试有限。


附1:转发BIND9默认是关闭的,如果需要声明可以在named.conf.options这样写
forwarders {};
forward only;

附2:如何关闭BIND9对于ls命令功能,对于有slave或者特殊需要的,用ip替换none即可
allow-transfer { none; };

freehostia上如何禁止列目录下的文件

突然发现freehostia默认可以列出没有默认文件目录下的文件,这个实在是很SB的默认配置。

尝试在.htaccess中添加一行Options -Indexes,结果网站顿时就HTTP 500 Internal Error,强大~~,怀疑是AllowOverride的权限等级不够

折腾半天,找到个折中替代方法,改为增加一行IndexIgnore *,这样目录列表会变成总是空的,看不到实际的文件,算是起到保护作用。

使用wget进行两个服务器间单向文件同步

之前曾经使用过FTPSync进行非实时网站同步的实现,结果发现wget已有类似功能,而且更加简单

例如:
wget -m --no-remove-listing -nH -P /home/xxx/bak/ ftp://username:password@www.xxx.com/*
务必注意最后ftp路径后面有个*,否则wget只会下载生成一个目录列表文件index.html,而不会同步文件

参数含义:
-m 开启单向镜像
--no-remove-listing 不生成目录列表文件index.html
-nH 不创建以主机名命名的目录
-P 下载保存路径

wget很强大,可以做很多参数配置,例如:
-w 下载间隔时间
-X 排除某些目录
......


-----------以下2009-11-05 23:00添加-----------
wget只能实现下载,远程如果删除了文件,本地不会同步删除,比较适合一次性将文件全部抓取回来或者不需要删除的情况;FTPSync则可以同步删除。

如何让没有Shell权限的用户可以使用Proftpd的FTP服务

默认Proftpd是需要检查连接用户在/etc/passwd中配置的shell类型是否在/etc/shells中存在的,所以默认配置了/sbin/nologin或/bin/false的用户登录FTP会提示530 Login incorrect

解决方法有两种:
1、将/sbin/nologin或/bin/false添加到/etc/shells中就可以
2、在Proftpd的配置文件/etc/proftpd.conf中关闭检查项RequireValidShell,具体可以参考Proftpd手册http://www.proftpd.org/docs/directives/linked/config_ref_RequireValidShell.html

非实时网站同步的实现

现状:
现有两个站点,分别称为SiteR和SiteF,两者都可以通过FTP管理,且SiteR有Shell权限并支持perl

目的:
将SiteF作为主站,定时将SiteF上的WEB内容和数据库数据同步到SiteR,同步是非实时且单向的

实现方法:
1、在SiteR上使用FTPSync.pl脚本实现通过FTP方式的SiteF到SiteR的文件同步(下载地址http://ossw.ibcl.at/FTPSync/

2、在SiteF上编写一个php页面,作用是定时将数据库数据导出成文本格式并压缩,核心代码如下,原理是使用system方法执行MySQL的备份命令mysqldump,同时使用find命令删除过期备份文件
[quote]$command = "mysqldump -h数据库地址 -u用户名 -p密码 --default-character-set=utf8 数据库名|gzip>生成的文本备份文件路径及名称";
system($command, $retval);

$command = "find 备份路径/*.gz -mtime +10 -exec rm {} \\;";
system($command, $retval);[/quote]

3、在SiteR上编写Shell脚本,核心代码如下
[quote]//远程调用SiteF备份页面,生成数据库备份
wget http://xxx.xxx/xxx/xxx.php

//同步远程文件到本地
ftpsync.pl ftpuser=FTP帐号 ftppasswd=FTP密码 本地目的路径 ftp://远程FTP源地址//[/quote]
如果源FTP地址是从根目录开始,最后要写两个/,这个貌似是FTPSync的一个BUG,我使用的是1.3.01

4、在cron中定时调用第3步的Shell脚本
[quote]#每天凌晨0点
0 0 * * * /xxx/xxx[/quote]

此方法的必备条件:
1、各个站点可通过FTP获取源文件
2、其中一个站点有Shell权限,且支持perl,且可以使用cron