分类目录归档:技术文章

FreeBSD服务程序的安全设置

目录 [隐藏]
1 服务程序的安全设置
1.1 Apache的安全设置
1.2 PHP安全设置
1.3 Mysql的安全设置
1.4 vsFTPd安全设置
1.5 SSH安全设置
2 操作系统FreeBSD所有条目
3 参见 
 
[编辑]服务程序的安全设置
到这里就是本文的重点所在了,我们将花费比较多的文字进行描述,当然,所以描述不一定是非常正确的,也希望能够对你有一些帮助。我们系统默认是运行了包括Apache、Mysql、vsFTPd,SSH等服务,我们以下进行一一讲解。

[编辑]Apache的安全设置
Apache的核心设置就是在 httpd.conf 里面,我们安装的Apache的目录是在 /usr/local/2/ 下,那么我们的配置文件就是在 /usr/local/2/conf/httpd.conf ,如果你是使用ports等安装的,配置文件应该是在/etc或/usr/local/etc目录下。使用ee或者vi打开配置文件:

  # ee /usr/local/apache2/conf/httpd.conf

下面我们就要进行比较多的安全设置了,基本的服务、端口、主目录等等设置就不说了,只讲与安全有关的设置。

(1)指定运行Apache服务的用户和组
这是比较重要的,因为权限是继承的,如果运行Apache服务的用户权限太高,那么很可能使得入侵者通过WebShell等就会对系统构成严重威胁。一般我们运行Apache的是nobody用户和nobody组。在httpd.conf的250-275行之间找到User和Group选项,比如我们默认设置如下(去掉了注释信息):

  <IfModule !mpm_winnt.c>;

  <IfModule !mpm_netware.c>;

  User nobody

  Group #-1

  </IfModule>;

  </IfModule>;

(2) Apache的日志文件
  Apache的日志文件是非常重要的,可以发现apache的运行状况和访问情况,对于判断入侵等有重要帮助。它的默认选项是:

  # 错误日志存放目录,默认是存放在apache安装目录的logs下

  ErrorLog logs/error_log

  # 日志记录的级别,级别有debug, info, notice, warn, error, crit等,默认是“warn”级别

  LogLevel warn

  # 访问日志记录的格式,每一种格式都有不同的内容,根据你的需要进行定制,以获取最多访问信息

  LogFormat "%h %l %u %t \"%r\" %>;s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

  LogFormat "%h %l %u %t \"%r\" %>;s %b" common

  LogFormat "%{Referer}i ->; %U" referer

  LogFormat "%{User-agent}i" agent

  # 使用上面格式的那一种,默认是使用common

  CustomLog logs/access_log common

  文件格式预定义的格式内容:

  %a 远程用户IP

  %A 本地httpd服务器的ip

  %f 传送的文件名

  %h 远程主机

  %m 请求方式

  %l identd给出的远程名

  %p 连接的httpd端口号

  %P 请求的httpd进程

  %t 时间

  %T 服务请求时间

你可以定制自己的日志格式,然后通过CustomLog logs/access_log common来进行调用。

注意,日志文件是由运行Apache的用户进行打开的,要注意该文件的安全,防止被黑客改写或者删除。

(3) Apache服务信息显示控制
在配置文件中有个选项是控制是否显示apache版本信息、主机名称、端口、支持的cgi等信息的:

  ServerSignature On

默认为On,那么将显示所有信息:

  我故意访问一个不存在的文件:http://www.target.com/404.html

  那么就会在给的错误提示中显示如下信息:

  Apache/2.0.53 (Unix) /4.3.11 Server at target.com Port 80

所有Apache和PHP的信息暴露无遗,这是很不安全的。当然同时还有Off和EMail选项,Off将不显示任何信息,EMail将显示管理员的邮箱地址,建议设为Off或者EMail,这样能够避免泄漏Apache服务器的信息给黑客。

(4) 目录浏览
  在httpd.conf中可以设置apache能够对一些没有索引文件的网页目录进行目录浏览:

  <Directory />;

  Options Indexes FollowSymLinks

  AllowOverride None

  </Directory>;

  这是不合适也不安全的,建议不需要目录浏览:

  <Directory />;

  Options FollowSymLinks

  AllowOverride None

  </Directory>;

(5) 用户主页
  设置httpd.conf中的:

  UserDir public_html

  能够使得每个使用系统的用户在自己的主目录下建立 public_html 目录后就能够把自己的网页放进该目录,然后通过:

  http://www.target.com/~用户名/网页 就能够显示自己的网页,这是不安全的,而且对于我们服务器来讲,这没有必要,所以我们直接关闭该功能:

  UserDir disabled

  或者把该内容改名,改成 一个黑客比较不容易猜到的文件名,比如:

  UserDir webserver_public_htmlpath

  也可以只允许部分用户具有该功能:

  UserDir enabled user1 user2 user3

(6) CGI执行目录
  如果你的apache要执行一些perl等cgi程序,那么就要设置一下选项:

  ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"

  但是这也给了黑客利用一些不安全的cgi程序来进行破坏,所以如果你不需要cgi的话,建议关闭该选项:

  #ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"

(7) 控制PHP脚本只能访问指定目录
  在httpd.conf添加如下内容:

  php_admin_value open_basedir /usr/www

  后面的路径是你需要PHP脚本能够访问的目录,如果PHP脚本想要访问其他目录将出项错误提示。

  ( 目录访问控制 (未完)

  这项内容最复杂,同时涉及的东西也比较多,我只能简单说一下,不清楚请参考其他文章。

  比如下面的内容:

  <Directory />;

  Options FollowSymLinks

  AllowOverride None

  </Directory>;

  就是允许访问每一个目录,里面设置的是允许执行的动作,一般包含的动作有:Options、AllowOverride、Order、Allow、Deny.

  Options是只对指定目录及其子目录能够执行的操作,Indexes、Includes、FollowSymLinks、ExecCGI、MultiViews、None、All等操作。

  AllowOverride是指定目录访问的权限,当然也可以通过 AccessFileName文件指定的 .htaccess 来控制。它的操作有:None、All、Options、FileInfo、AuthConfit、Limit等。

  Order、Allow、Deny三个指令必须配合来控制目录访问权限。Order指定检查次序的规则,比如Order Allow, Deny,表示先按Allow检查,如果不匹配再按Deny进行检查。Order Deny, Allow ,表示先按Deny规则检查,如果不满足条件,再按Allow进行检查。

  [NextPage]

  控制目录访问权限的文件

  默认在Unix平台下能够使用 .htaccess 来对目录权限进行规则定义,但是这是不安全的,建议关闭,默认的选项:

  AccessFileName .htaccess

  建议设成:

  #AccessFileName .htaccess

  全部目录权限定义使用httpd.conf中的定义,不使用 .htaccess.

(9) 用户访问认证
  这个技术非常重要,能够控制一些非法用户访问本内容。假设我们的网站: http://www.target.com/admin 是我们的后台管理目录,我不允许一些非法用户进行访问,那么我就必须设定对该目录访问是需要验证的。

  先在httpd.conf中加入要进行访问认证的目录:

  <Directory "/usr/www/admin">;

  authtype basic

  authname "rivate"

  authuserfile /usr/local/apache/bin/admin.dat

  require user login_user

  Options Indexes FollowSymlinks MultiViews

  AllowOverride None

  </Directory>;

  上面我们就设置了我们的 /usr/www/admin目录是必须进行认证才能访问的,接着我们设置访问密码:

  # /usr/local/apahche/bin/htpasswd -c /usr/local/apache/bin/admin.dat login_name

  New password: *****

  Re-type new password: *****

  Adding password for user login_name

  那么下次任何用户访问http://www.target.com/admin目录的时候就需要输入用户名login_name和你设置的密码。

[编辑]PHP安全设置
PHP本身再老版本有一些问题,比如在 php4.3.10和php5.0.3以前有一些比较严重的bug,所以推荐使用新版。另外,目前闹的轰轰烈烈的SQL Injection也是在PHP上有很多利用方式,所以要保证安全,PHP代码编写是一方面,PHP的配置更是非常关键。

我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行php能够更安全。

整个PHP中的安全设置主要是为了防止phpshell和SQL Injection的攻击,一下我们慢慢探讨。我们先使用任何编辑工具打开/etc/local/apache2/conf/php.ini,如果你是采用其他方式安装,配置文件可能不在该目录。

(1) 打开php的安全模式
  php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,但是默认的php.ini是没有打开安全模式的,我们把它打开:

  safe_mode = on

(2) 用户组安全
  当safe_mode打开时,safe_mode_gid被关闭,那么php脚本能够对文件进行访问,而且相同组的用户也能够对文件进行访问。

  建议设置为:

  safe_mode_gid = off

  如果不进行设置,可能我们无法对我们服务器网站目录下的文件进行操作了,比如我们需要对文件进行操作的时候。

(3) 安全模式下执行程序主目录
  如果安全模式打开了,但是却是要执行某些程序的时候,可以指定要执行程序的主目录:

  safe_mode_exec_dir = /usr/bin

  一般情况下是不需要执行什么程序的,所以推荐不要执行系统程序目录,可以指向一个目录,然后把需要执行的程序拷贝过去,比如:

  safe_mode_exec_dir = /tmp/cmd

  但是,我更推荐不要执行任何程序,那么就可以指向我们网页目录:

  safe_mode_exec_dir = /usr/www

(4) 安全模式下包含文件
  如果要在安全模式下包含某些公共文件,那么就修改一下选项:

  safe_mode_include_dir = /usr/www/include/

  其实一般php脚本中包含文件都是在程序自己已经写好了,这个可以根据具体需要设置。

(5) 控制php脚本能访问的目录
  使用open_basedir选项能够控制PHP脚本只能访问指定的目录,这样能够避免PHP脚本访问/etc/passwd等文件,一定程度上限制了phpshell的危害,我们一般可以设置为只能访问网站目录:

  open_basedir = /usr/www

(6) 关闭危险函数
  如果打开了安全模式,那么函数禁止是可以不需要的,但是我们为了安全还是考虑进去。比如,我们觉得不希望执行包括system()等在那的能够执行命令的php函数,或者能够查看php信息的phpinfo()等函数,那么我们就可以禁止它们:

  disable_functions = system,passthru,exec,shell_exec,popen,phpinfo

  如果你要禁止任何文件和目录的操作,那么可以关闭很多文件操作

  disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir,rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown

  以上只是列了部分不叫常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,就能够抵制大部分的phpshell了。

  [NextPage]

(7) 关闭PHP版本信息在http头中的泄漏
  我们为了防止黑客获取服务器中php版本的信息,可以关闭该信息斜路在http头中:

  expose_php = Off

  比如黑客在 telnet www.target.com 80 的时候,那么将无法看到PHP的信息。

(8) 关闭注册全局变量
  在PHP中提交的变量,包括使用POST或者GET提交的变量,都将自动注册为全局变量,能够直接访问,这是对服务器非常不安全的,所以我们不能让它注册为全局变量,就把注册全局变量选项关闭:

  register_globals = Off

  当然,如果这样设置了,那么获取对应变量的时候就要采用合理方式,比如获取GET提交的变量var,那么就要用$_GET[‘var’]来进行获取,这个php程序员要注意。

(9) 打开magic_quotes_gpc来防止SQL注入
  SQL注入是非常危险的问题,小则网站后台被入侵,重则整个服务器沦陷,所以一定要小心。php.ini中有一个设置:

  magic_quotes_gpc = Off

  这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换,比如把 ‘ 转为 \’等,这对防止sql注射有重大作用。所以我们推荐设置为:

  magic_quotes_gpc = On

(10) 错误信息控制
  一般php在没有连接到数据库或者其他情况下会有提示错误,一般错误信息中会包含php脚本当前的路径信息或者查询的SQL语句等信息,这类信息提供给黑客后,是不安全的,所以一般服务器建议禁止错误提示:

  display_errors = Off

  如果你却是是要显示错误信息,一定要设置显示错误的级别,比如只显示警告以上的信息:

  error_reporting = E_WARNING & E_ERROR

  当然,我还是建议关闭错误提示。

(11) 错误日志
  建议在关闭display_errors后能够把错误信息记录下来,便于查找服务器运行的原因:

  log_errors = On

  同时也要设置错误日志存放的目录,建议根apache的日志存在一起:

  error_log = /usr/local/apache2/logs/php_error.log

注意:给文件必须允许apache用户的和组具有写的权限。
[编辑]Mysql的安全设置
  我们把Mysql安装在 /usr/local/mysql目录下,我们必须建立一个用户名为mysql,组为mysql的用户来运行我们的mysql,同时我们把它的配置文件拷贝到 /etc目录下:

  # cp suport-files/my-medium.cnf /etc/my.cnf

  chown root:sys /etc/my.cnf

  chmod 644 /etc/my.cnf

  使用用户mysql来启动我们的mysql:

  # /usr/local/mysql/bin/mysqld_safe -user=mysql &

(1) 修改root用户的的口令
  缺省安装的mysql是没有密码的,所以我们要修改,以防万一。下面采用三种方式来修改root的口令。

  * 用mysqladmin命令来改root用户口令

  # mysqladmin -uroot password test

  这样,MySQL数据库root用户的口令就被改成test了。(test只是举例,我们实际使用的口令一定不能使用这种易猜的弱口令)

  * 用set password修改口令:

  mysql>; set password for root@localhost=password(’test’);

  这时root用户的口令就被改成test了。

  * 直接修改user表的root用户口令

  mysql>; use mysql;

  mysql>; update user set password=password(’test’) where user=’root’;

  mysql>; flush privileges;

  这样,MySQL数据库root用户的口令也被改成test了。其中最后一句命令flush privileges的意思是强制刷新内存授权表,否则用的还是缓冲中的口令,这时非法用户还可以用root用户及空口令登陆,直到重启MySQL服务器。

(2) 删除默认的数据库和用户
  我们的数据库是在本地,并且也只需要本地的php脚本对mysql进行读取,所以很多用户不需要。mysql初始化后会自动生成空用户和test库,这会对数据库构成威胁,我们全部删除。

  我们使用mysql客户端程序连接到本地的mysql服务器后出现如下提示:

  mysql>; drop database test;

  mysql>; use mysql;

  mysql>; delete from db;

  mysql>; delete from user where not(host="localhost" and user="root";

  mysql>; flush privileges;

(3) 改变默认mysql管理员的名称
  这个工作是可以选择的,根据个人习惯,因为默认的mysql的管理员名称是root,所以如果能够修改的话,能够防止一些脚本小子对系统的穷举。我们可以直接修改数据库,把root用户改为"admin"

  mysql>; use mysql;

  mysql>; update user set user="admin" where user="root";

  mysql>; flush privileges;

(4) 提高本地安全性
  提高本地安全性,主要是防止mysql对本地文件的存取,比如黑客通过mysql把/etc/passwd获取了,会对系统构成威胁。mysql对本地文件的存取是通过SQL语句来实现,主要是通过Load DATA LOCAL INFILE来实现,我们能够通过禁用该功能来防止黑客通过SQL注射等获取系统核心文件。

  禁用该功能必须在 my.cnf 的[mysqld]部分加上一个参数:

  set-variable=local-infile=0

(5) 禁止远程连接mysql
  因为我们的mysql只需要本地的php脚本进行连接,所以我们无需开socket进行监听,那么我们完全可以关闭监听的功能。

  有两个方法实现:

  * 配置my.cnf文件,在[mysqld]部分添加 skip-networking 参数

  * mysqld服务器中参数中添加 ——skip-networking 启动参数来使mysql不监听任何TCP/IP连接,增加安全性。如果要进行mysql的管理的话,可以在服务器本地安装一个phpMyadmin来进行管理。

(6) 控制数据库访问权限
  对于使用php脚本来进行交互,最好建立一个用户只针对某个库有 update、select、delete、insert、drop table、create table等权限,这样就很好避免了数据库用户名和密码被黑客查看后最小损失。

  比如下面我们创建一个数据库为db1,同时建立一个用户test1能够访问该数据库。

  mysql>; create database db1;

  mysql>; grant select,insert,update,delete,create,drop privileges on db1.* to test1@localhost identified by ‘admindb’;

  以上SQL是创建一个数据库db1,同时增加了一个test1用户,口令是admindb,但是它只能从本地连接mysql,对db1库有select,insert,update,delete,create,drop操作权限。

(7) 限制一般用户浏览其他用户数据库
  如果有多个数据库,每个数据库有一个用户,那么必须限制用户浏览其他数据库内容,可以在启动MySQL服务器时加——skip-show-database 启动参数就能够达到目的。

(8) 忘记mysql密码的解决办法
  如果不慎忘记了MySQL的root密码,我们可以在启动MySQL服务器时加上参数——skip-grant-tables来跳过授权表的验证 (。/safe_mysqld ——skip-grant-tables &,这样我们就可以直接登陆MySQL服务器,然后再修改root用户的口令,重启MySQL就可以用新口令登陆了。

(9) 数据库文件的安全
  我们默认的mysql是安装在/usr/local/mysql目录下的,那么对应的数据库文件就是在/usr/local/mysql/var目录下,那么我们要保证该目录不能让未经授权的用户访问后把数据库打包拷贝走了,所以要限制对该目录的访问。

  我们修改该目录的所属用户和组是mysql,同时改变访问权限:

  # chown -R mysql.mysql /usr/local/mysql/var

  # chmod -R go-rwx /usr/local/mysql/var

(10) 删除历史记录
  执行以上的命令会被shell记录在历史文件里,比如bash会写入用户目录的。bash_history文件,如果这些文件不慎被读,那么数据库的密码就会泄漏。用户登陆数据库后执行的SQL命令也会被MySQL记录在用户目录的。mysql_history文件里。如果数据库用户用SQL语句修改了数据库密码,也会因。mysql_history文件而泄漏。所以我们在shell登陆及备份的时候不要在-p后直接加密码,而是在提示后再输入数据库密码。

  另外这两个文件我们也应该不让它记录我们的操作,以防万一。

  # rm .bash_history .mysql_history

  # ln -s /dev/null .bash_history

  # ln -s /dev/null .mysql_history

  (11) 其他

  另外还可以考虑使用chroot等方式来控制mysql的运行目录,更好的控制权限,具体可以参考相关文章。

  [NextPage]

[编辑]vsFTPd安全设置
  vsFTPd是一款非常着名的ftp daemon程序,目前包括Redhat.com在内很多大公司都在使用,它是一款非常安全的程序,因为它的名字就叫:Very Secure FTP Daemon (非常安全的FTP服务器)。

  vsftpd设置选项比较多,涉及方方面面,我们下面主要是针对安全方面进行设置。

  目前我们的需求就是使用系统帐户同时也作为是我们的FTP帐户来进行我们文件的管理,目前假设我只需要一个帐户来更新我的网站,并且我不希望该帐户能够登陆我们的系统,比如我们的网站的目录是在/usr/www下面,那么我们新建一个用户ftp,它的主目录是/usr/www,并且它的shell是 /usr/sbin/nologin,就是没有shell,防止该用户通过ssh等登陆到系统。

  下面在进行系统详尽的设置,主要就是针对vsftpd的配置文件vsftpd.conf文件的配置。

(1) 禁止匿名用户访问, 我们不需要什么匿名用户,直接禁止掉:
  anonymous_enable=NO

(2) 允许本地用户登陆,因为我们需要使用ftp用户来对我们网站进行管理:
  local_enable=YES

(3) 只允许系统中的ftp用户或者某些指定的用户访问ftp,因为系统中帐户众多,不可能让谁都访问。
  打开用户文件列表功能:

  userlist_enable=YES

  只允许用户文件列表中的用户访问ftp:

  userlist_deny=NO

  用户名文件列表路径:

  userlist_file=/etc/vsftpd.user_list

  然后在/etc下建立文件 vsftpd.user_list 文件,一行一个,把用户ftp加进去,同时也可以加上你允许访问的系统帐户名。

(4) 禁止某些用户登陆ftp:
  pam_service_name=vsftpd

  指出VSFTPD进行PAM认证时所使用的PAM配置文件名,默认值是vsftpd,默认PAM配置文件是/etc/pam.d/vsftpd.

  /etc/vsftpd.ftpusers

  VSFTPD禁止列在此文件中的用户登录FTP服务器,用户名是一行一个。这个机制是在/etc/pam.d/vsftpd中默认设置的。

  这个功能和(3)里的功能有点类似,他们俩能结合使用,那样就最好了。

(5) 把本地用户锁定在自己的主目录,防止转到其他目录,比如把/etc/passwd给下载了:
  chroot_local_users=NO

  chroot_list_enable=YES

  chroot_list_file=/etc/vsftpd.chroot_list

  然后在/etc下建立vsftpd.chroot_list文件,里面把我们要限制的本地帐户加进去,一行一个,我们加上ftp,防止它登陆到系统。

(6) 隐藏文件真实的所有用户和组信息,防止黑客拿下ftp后查看更多系统用户信息:
  hide_ids=YES

(7) 取消ls -R命令,节省资源,因为使用该命令,在文件列表很多的时候将浪费大量系统资源:
  ls_recurse_enable=NO

(8) 上传文件的默认权限,设置为022:
  local_umask=022

  如果要覆盖删除等,还要打开:

  write_enable=YES

(9) ftp的banner信息,为了防止黑客获取更多服务器的信息,设置该项:
  ftpd_banner=banner string

  把后面的banner string设为你需要的banner提示信息,为了安全,建议不要暴露关于vsFTPd的任何信息。

  另外,如果你的信息比较多的话,可以设置为提示信息是读取一个文件中的信息:

  banner_file=/directory/vsftpd_banner_file

(10) 打开日志功能:
  xferlog_enable=YES

  同时设置日志的目录:

  xferlog_file=/var/log/vsftpd.log

  启用详细的日志记录格式:

  xferlog_enable=YES

(11) 如果打开虚用户功能等,那么建议关闭本地用户登陆:
  local_enable=NO

  vsFTPd还有很多安全设置,毕竟人家的名字就是:Very Secure FTP Daemon,反正它的溢出漏洞什么的是很少的,如果要更安全,建议按照自己的需要设置vsftpd,设置的好,它绝对是最安全的。

[编辑]SSH安全设置
  SSH是一个基于SSL的安全连接远程管理的服务程序,主要出现就是为了解决telnet、rlogin、rsh等程序在程序交互过程中存在明文传输易被监听的问题而产生的,目前基本上是推荐使用ssh来代替telnet、rlogin、rsh等远程管理服务。

  ssh能够直接在windows平台下通过Secure SSH Client等客户端工具进行连接管理,目前最流行的服务器端就是OpenSSH程序,目前最新版本是OpenSSH4.0版,详细可以参考www.openssh.com网站。

  OpenSSH在FreeBSD下已经集成安装了,FreeBSD5.3下的OpenSSH版本是3.8.1,建议ports升级到4.0.

  主要的安全配置文件是/etc/ssh/sshd_config文件,我们编辑该文件。

(1) 使用protocol 2代替protocol 1,SSH2更加安全,可以防止攻击者通过修改携带的版本banner来劫持(hijacking)启动会话进程并降低到protocol 1.注释掉protocol 2,1 改用下面语句代替:

  protocol 2

(2) 合理设置最大连接数量, 防止DOS攻击

  MaxStartups 5:50:10

(3)关闭X11forwording ,防止会话劫持

  X11Forwarding no

(4)建议不使用静态密码,而使用DSA 或RSA KEY,修改如下内容可以关闭使用密码认证:

  PasswordAuthentication no

(5)可以限制某个组或光是单个用户访问shell

  AllowGroups wheel

  或者

  AllowUsers heiyeluren

  (6) 限制root用户登陆,主要是为了防止暴力破解

  PermitRootLogin no

(7) 不允许口令为空的用户登陆

  PermitEmptyPasswords no

(8)使用TCP wrappers来限制一些访问,修改/etc/hosts.allow文件,注释掉"ALL : ALL : allow",增加如下内容:

  sshd:localhost:allow

  sshd:friendlcomputer:allow

  sshd:all : deny

  #相关命令:

  #chsh -s /sbin/nologin user

 

FreeBSD系统安全设置

系统安全设置
1. 用户控制
尽量少的用户,我们的FTP帐户是和系统帐户绑定在一起的,所以我们添加用户的时候先建立一个目录,然后把新建的用户主目录指向到该目录下。假设我需要一个用户能够管理我的网站,而我网站的目录是在 /usr/www 目录下,那么我们新建立的用户 www_user 的主目录就指向 /usr/www 目录,同时它的shell是没有的:/usr/sbin/nologin ,主要是为了防止它通过ssh登陆到系统。同时FTP的密码也要设置的非常复杂,防止黑客通过暴力破解获得FTP权限。另外还要说道我们的root用户的密码,我想最少应该不要少于10位的数字+字母+字符的密码(我的密码是18位),否则是非常不安全的,如果密码简单,那么黑客通过短时间的暴力破解 SSH中的root帐户,不用几天,系统就可能被攻破了,同时也建议最少一个月更改一次root用户的密码。(强烈建议一般帐户不要有登陆系统的权限,就是把shell设为/usr/sbin/nologin)

一般如果要使用root权限建议建立一个属于wheel组的小用户,然后登陆后通过su命令提升为root用户进行管理,如果黑客通过破解了我们普通用户的权限后登陆系统,也不能直接通过root权限进行管理,这是一种安全防范的简单方法。

2. 文件访问控制
有时候被黑客入侵后拿到了小权限用户,比如传了一个WebShell到系统中,那么对方很可能会把 /etc/passwd 等内容直接读取出来,同时查看/etc/master.passwd中对加密后的root用户的密码hash进行破解,最后拿到密码进行登陆系统。那么我们就要控制部分文件只有root能够访问,其他用户无权访问。比如uname,gcc等,如果黑客拿到小权限用户后就会查看系统版本,然后找到该版本系统对应的溢出程序,使用gcc来进行编译,如果我们能够限制黑客访问uname和gcc等程序,能在一定程度上减缓黑客入侵的脚步。

使用chmod来改变某个文件的权限信息,比如我要 /etc/passwd 和 /etc/master.passwd 文件只能允许root访问:

使用八进制数字来设置

  # chmod 700 /etc/passwd

  # chmod 700 /etc/master.passwd

使用字符标记来进行设置

  # chmod u+w+r+x,go-w-r-x /etc/passwd

  # chmod u+w+r+x,go-w-r-x /etc/master.passwd

系统中有多个重要文件需要设置控制访问权限,一定要控制好,否则将会构成重要威胁。

3. 系统服务和端口控制
端口开的越多就越给黑客多一个入侵的机会,服务越多,危险越大,因为你不知道那些服务是不是有潜在的漏洞或者又发现了新的漏洞,所以尽量少的服务,比如sendmail默认是打开的,那么些建议你把sendmail关闭,关闭防范是在 /etc/rc.conf中加上:

  sendmail_enable = "NONE",如果设为"NO"那么只能够关闭掉pop3服务,不能关闭smtp的服务,所以要设置为"NONE".

系统中最好除了我们能够看到的Apache、Mysql、vsFTPd、SSH之外不要打开其他任何端口和服务。基本的方式是使用netstat -a 查看打开的端口,然后从对应的端口来找相关的服务,比如我们这里应该只允许开的端口有 21, 22, 80, 3306等,如果有其他端口,那么一定要仔细检查,很可能是黑客的后门或者是会对系统安全构成威胁的服务。同时有些服务不需要监听网络连接的话,只是需要本地的连接,比如Mysql,那么就可以关闭Socket监听,这个将在Mysql安全设置中讲解,另外,可以通过防火墙来控制部分端口访问和连接状况,比如Mysql的3306端口只允许192.168.0.1访问,那么我们就在ipfw里添加规则:

  ipfw add 10001 allow tcp from 192.168.0.1 to 10.10.10.1 80 in

  这样就能够防止黑客来访问服务器上的Mysql服务。具体防火墙的设置将在下面“防火墙设置”中详细讲解。

4. 日志管理和控制 (略)
  [NextPage]

5. 文件指纹检测
文件指纹就是我们文件的基本信息,比如文件权限、文件所属用户/组、文件最后修改日期、文件大小等等,这些都是重要信息,一般[[[黑客]]入侵后都可能修改文件,那么文件指纹就不一样了。另外,文件的md5校验值也属于文件的指纹的一种。

为了防止黑客篡改系统中的部分核心文件,比如 /etc/passwd, /etc/shadow, /etc/inetd.conf 等等,那么我们就可以考虑把部分重要文件进行备份,同时做一份目前有的文件的一个指纹保留,比如把 /etc,/bin, /usr/bin 目录下的文件进行指纹保留:

# ls -l /etc >; /var/back/etc.txt
# ls -l /bin >; /var/back/bin.txt
# ls -l /bin >; /var/back/usrbin.txt

当然,还有就是给每个重要的文件加上md5校验值,如果觉得不对劲的时候就进行匹配,保证文件的安全。

你可以给你觉得需要做指纹备份的目录进行备份,一般这是为了以后被黑客入侵后的系统检测和系统恢复。比如可以通过文件被修改的时间来确定是不是被入侵,比如可以对比看 /etc/inetc.conf文件和备份的文件有什么不同来确定是不是安装了服务型后门等。

6. 系统指纹泄漏和防范
一般黑客为了入侵某个系统,一定会先进行扫描等工作,扫描包括目标系统的端口开放情况和服务器使用服务程序和操作系统情况。比如很简单的手工检测Web服务的指纹:

# telnet target.com 80

那么就很可能返回Apache和PHP的版本信息,那么同时也可能使用扫描工具对Mysql、vsFTPd、SSH等服务的端口进行扫描,获取这些服务的指纹。多暴露一份系统信息,那么系统就多一份危险。那么解决办法就是把服务器上服务程序的Banner全部修改掉,从而能够迷惑黑客。

下面简单的说一些修改那些服务Banner的方法。

  *

  修改httpd.conf文件,设置以下选项:

  ServerSignature Off

  ServerTokens Prod

上面的适用apache1***, apache 2.0这些都是默认 , 不过还是有server=Apache字样, 若要完全去掉需重新编译。

彻底地去掉banner, 修改httpd.h:

  Include/httpd.h

  Define SERVER_BASEVENDOR "Apache Group"

  Define SERVER_PRODUCTVENDOR "Apache"

  Define SERVER_BASEVERSION "1.3.27"

后从新编译Apache就能够完全去掉了。

  *

  在php.ini中设置 expose_php = Off ,那么将无法在 http头信息中看到php的版本信息。

  * Mysql

  * vsFTPd

vsFTPd基本上是无法获取到一些关于vsFTPd的banner信息的,不过因为vsFTPd默认的banner信息是"Welcome to FTP Server!"对于高手来说,还是能够猜测到一点,所以我们要彻底改掉。修改vsFTPd的配置文件 vsftpd.conf 中的下面选项:

Ftpd_banner=xxxxx

把后面的xxxxx改为你想要的banner信息。

  * SSH

好象FreeBSD下默认安装的SSH被telnet target.com 22 的时候会显示SSH和FreeBSD的信息,简直是个大祸害,什么都告诉别人了,但是目前为止我还不知道怎么修改,知道的高手请指点。

7. 系统内核安全
FreeBSD有个比较强的功能,就是能够定义系统内核的安全等级,主要是为了防止内核后门专门定制的,能通过不同的等级限制对内核的访问和对防火墙等的修改。我们首先要开启系统的安全等级,然后设定安全等级,我们打开 /etc/rc.conf:

  # ee /etc/rc.conf

加入下面的内容:

  kern_securelevel_enable="YES"

  kern_securelevel="-1"

第一句是打开安全等级,第二句是定义等级。它一共五个等级,下面说说不同之处。

  * kern_securelevel -1:这是系统默认级别,没有提供任何内核的保护错误;

  * kern_securelevel 0:基本上作用不多,当你的系统刚启动就是0级别的,当进入多用户模式的时候就自动变成1级了。

  * kern_securelevel 1:在这个级别上,有如下几个限制:

  a. 不能通过kldload或者kldunload加载或者卸载可加载内核模块;

  b. 应用程序不能通过/dev/mem或者/dev/kmem直接写内存;

  c. 不能直接往已经装在(mounted)的磁盘写东西,也就是不能格式化磁盘,但是可以通过标准的内核接口执行写操作;

  d. 不能启动X-windows,同时不能使用chflags来修改文件属性;

  * kern_securelevel 2:在 1 级别的基础上还不能写没装载的磁盘,而且不能在1秒之内制造多次警告,这个是防止DoS控制台的;

  * kern_securelevel 3:在 2 级别的级别上不允许修改IPFW防火墙的规则。

如果你已经装了防火墙,并且把规则设好了,不轻易改动,那么建议使用3级别,如果你没有装防火墙,而且还准备装防火墙的话,不建议使用。我们这里推荐使用 2 级别,能够避免比较多对内核攻击。

8. 系统安全优化
一般优化系统主要是重新编译内核,去掉一些不要的驱动等等,你可以参考我在我Blog上写的关于编译内核的文章。我们这里对网络和内核一些选项进行优化和安全设置。编辑 /etc/sysctl.conf 文件,在里面加入如下内容:(有注释)

  #最大的待发送TCP数据缓冲区空间

  net.inet.tcp.sendspace=65536

  #最大的接受TCP缓冲区空间

  net.inet.tcp.recvspace=65536

  #最大的接受UDP缓冲区大小

  net.inet.udp.sendspace=65535

  #最大的发送UDP数据缓冲区大小

  net.inet.udp.maxdgram=65535

  #本地套接字连接的数据发送空间

  net.local.stream.sendspace=65535

  #加快网络性能的协议

  net.inet.tcp.rfc1323=1

  net.inet.tcp.rfc1644=1

  net.inet.tcp.rfc3042=1

  net.inet.tcp.rfc3390=1

  #最大的套接字缓冲区

  kern.ipc.maxsockbuf=2097152

  #系统中允许的最多文件数量

  kern.maxfiles=65536

  #每个进程能够同时打开的最大文件数量

  kern.maxfilesperproc=32768

  #当一台计算机发起TCP连接请求时,系统会回应ACK应答数据包。该选项设置是否延迟ACK应答数据包,把它和包含数据的数据包一起发送,在高速网络和低负载的情况下会略微提高性能,但在网络连接较差的时候,对方计算机得不到应答会持续发起连接请求,反而会降低性能。

  net.inet.tcp.delayed_ack=0

  #屏蔽ICMP重定向功能

  net.inet.icmp.drop_redirect=1

  net.inet.icmp.log_redirect=1

  net.inet.ip.redirect=0

  net.inet6.ip6.redirect=0

  #防止ICMP广播风暴

  net.inet.icmp.bmcastecho=0

  net.inet.icmp.maskrepl=0

  #限制系统发送ICMP速率

  net.inet.icmp.icmplim=100

  #安全参数,编译内核的时候加了options TCP_DROP_SYNFIN才可以用

  net.inet.icmp.icmplim_output=0

  net.inet.tcp.drop_synfin=1

  #设置为1会帮助系统清除没有正常断开的TCP连接,这增加了一些网络带宽的使用,但是一些死掉的连接最终能被识别并清除。死的TCP连接是被拨号用户存取的系统的一个特别的问题,因为用户经常断开modem而不正确的关闭活动的连接

  net.inet.tcp.always_keepalive=1

  #若看到net.inet.ip.intr_queue_drops这个在增加,就要调大net.inet.ip.intr_queue_maxlen,为0最好

  net.inet.ip.intr_queue_maxlen=1000

  #防止DOS攻击,默认为30000

  net.inet.tcp.msl=7500

  #接收到一个已经关闭的端口发来的所有包,直接drop,如果设置为1则是只针对TCP包

  net.inet.tcp.blackhole=2

  #接收到一个已经关闭的端口发来的所有UDP包直接drop

  net.inet.udp.blackhole=1

  #为网络数据连接时提供缓冲

  net.inet.tcp.inflight.enable=1

  #如果打开的话每个目标地址一次转发成功以后它的数据都将被记录进路由表和arp数据表,节约路由的计算时间,但会需要大量的内核内存空间来保存路由表

  net.inet.ip.fastforwarding=0

  #kernel编译打开options POLLING功能,高负载情况下使用低负载不推荐SMP不能和polling一起用

  #kern.polling.enable=1

  #并发连接数,默认为128,推荐在1024-4096之间,数字越大占用内存也越大

  kern.ipc.somaxconn=32768

  #禁止用户查看其他用户的进程

  security.bsd.see_other_uids=0

  #设置kernel安全级别

  kern.securelevel=0

  #记录下任何TCP连接

  net.inet.tcp.log_in_vain=1

  #记录下任何UDP连接

  net.inet.udp.log_in_vain=1

  #防止不正确的udp包的攻击

  net.inet.udp.checksum=1

  #防止DOS攻击

  net.inet.tcp.syncookies=1

  #仅为线程提供物理内存支持,需要256兆以上内存

  kern.ipc.shm_use_phys=1

  # 线程可使用的最大共享内存

  kern.ipc.shmmax=67108864

  # 最大线程数量

  kern.ipc.shmall=32768

  # 程序崩溃时不记录

  kern.coredump=0

  # lo本地数据流接收和发送空间

  net.local.stream.recvspace=65536

  net.local.dgram.maxdgram=16384

  net.local.dgram.recvspace=65536

  # 数据包数据段大小,ADSL为1452.

  net.inet.tcp.mssdflt=1460

  # 为网络数据连接时提供缓冲

  net.inet.tcp.inflight_enable=1

  # 数据包数据段最小值,ADSL为1452

  net.inet.tcp.minmss=1460

  # 本地数据最大数量

  net.inet.raw.maxdgram=65536

  # 本地数据流接收空间

  net.inet.raw.recvspace=65536

  #ipfw防火墙动态规则数量,默认为4096,增大该值可以防止某些病毒发送大量TCP连接,导致不能建立正常连接

  net.inet.ip.fw.dyn_max=65535

  #设置ipf防火墙TCP连接空闲保留时间,默认8640000(120小时)

  net.inet.ipf.fr_tcpidletimeout=864000

 

route命令

route命令可以在CMD DOS窗口中执行,主要看看route delete 和 route add。

route参数说明:

Manipulates network routing tables.

ROUTE [-f] [-p] [command [destination]
[MASK netmask] [gateway] [METRIC metric] [IF interface]

-f Clears the routing tables of all gateway entries. If this is
used in conjunction with one of the commands, the tables are
cleared prior to running the command.
-p When used with the ADD command, makes a route persistent across
boots of the system. By default, routes are not preserved
when the system is restarted. Ignored for all other commands,
which always affect the appropriate persistent routes. This
option is not supported in Windows 95.
command One of these:
PRINT Prints a route
ADD Adds a route
DELETE Deletes a route
CHANGE Modifies an existing route
destination Specifies the host.
MASK Specifies that the next parameter is the ‘netmask’ value.
netmask Specifies a subnet mask value for this route entry.
If not specified, it defaults to 255.255.255.255.
gateway Specifies gateway.
interface the interface number for the specified route.
METRIC specifies the metric, ie. cost for the destination.

All symbolic names used for destination are looked up in the network database
file NETWORKS. The symbolic names for gateway are looked up in the host name
database file HOSTS.

If the command is PRINT or DELETE. Destination or gateway can be a wildcard,
(wildcard is specified as a star ‘*’), or the gateway argument may be omitted.

If Dest contains a * or ?, it is treated as a shell pattern, and only
matching destination routes are printed. The ‘*’ matches any string,
and ‘?’ matches any one char. Examples: 157.*.1, 157.*, 127.*, *224*.
Diagnostic Notes:
Invalid MASK generates an error, that is when (DEST & MASK) != DEST.
Example> route ADD 157.0.0.0 MASK 155.0.0.0 157.55.80.1 IF 1
The route addition failed: The specified mask parameter is invalid.
(Destination & Mask) != Destination.

Examples:

> route PRINT
> route ADD 157.0.0.0 MASK 255.0.0.0 157.55.80.1 METRIC 3 IF 2
destination^ ^mask ^gateway metric^ ^
Interface^
If IF is not given, it tries to find the best interface for a given
gateway.
> route PRINT
> route PRINT 157* …. Only prints those matching 157*
> route CHANGE 157.0.0.0 MASK 255.0.0.0 157.55.80.5 METRIC 2 IF 2

CHANGE is used to modify gateway and/or metric only.
> route PRINT
> route DELETE 157.0.0.0
> route PRINT

PHP has encountered an Access Violation[转]

改PHP.INI

1.将;upload_tmp_dir该行的注释符,即前面的分号“;”去掉,使该行在php.ini文档中起作用。upload_tmp_dir是用来定义上传文件存放的临时路径,在这里你还可以给其定义一个绝对路径,例如:upload_tmp_dir = d:upload  当然,此时你的d:upload目录必须有读写权限。

2.出现这样的错误语句一般是因为你的php.ini中关于session.save_path一项没有设置好,解决的方法是将session.save_path和session.cookie_path 设置置为
  session_save_path = c:\temp
  session.cookie_path = c:\temp
  然后在c:\目录下建立一个temp目录,

 
下面是其他的处理方法
 
第一种可能:

 

去掉 php中 eaccelerator 的扩展
这样做能够解决您的问题,不过可能会加重系统负担
因为eaccelerator主要是为了节省系统资源的东西

 

具体做法是找到php.ini
如果是我帮您配置的,一般在c://php.ini或者 c:/winnt/.ini 或者c:/windows/.ini

 

去掉

 

zend_extension_ts="C:\php\extensions\eaccelerator_win_xxx.dll"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="c:\temp"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9" 字串8

ea主要是在unix环境下开发的,但是作者忽略到windows实际上不像u主机那样,是没有u主机的那种内存共享机制的
这个bug已经提交给他们了,希望0.9.5能够解决 字串7

当然,如果您的机器这个问题不严重,建议还是保留,ea是一块非常优秀的Php缓存+加速软件
配合zo使用,将会降低系统负担 50%-80%左右,提高负载能力、速度和效率 200%左右 字串2

  字串2

第二种可能 字串2

session_save_path 需要设定一个实际的物理路径,并且该目录需要everyone的所有权限,类似U主机的0777

  字串6

第三种可能
c:/winnt/temp 或者 c:/windows/temp
也需要everyone的所有权限,类似U主机的0777

第四种可能
您的内存严重不足,查看一下,如果有问题,请加内存,最好是一次加两条
比如加1G内存,最好是加2条一模一样的512M。否则没有启用双通道,效果也很一般

  字串2

第五种可能
ZendOptimizer和php的搭配不是很好
换个版本试试看
目前比较稳定的搭配是
php4.3.11+zo 2.5.10a
或者php4.4.1+zo 3.0 beta2 字串7

 

第六种可能

这种多属于用win2003的用户
他们在应用池中设定了限制
比如多长时间回收,最大使用内存多少等等
这些设置势必造成这个经典的php错误
木头经过数以百计的测试,敢担保问题会出现在这里。 字串

IIS默认浏览文件支持中文命名

 

 1、在客户端修改IE设置
把"总是以UTF-8发送URL"设置为不选中。
2、在Web服务器端修改注册表
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\INETINFO_PARAMETERS\FAVORdbCS 把1改成0,之后重新启动IIS即可。
如果此值已经是0,仍然无法支持中文路径,那么可能是URLSCAN为防止UNICODE漏洞而拦截了。
那么:
对winnt\system32\inetsrv\urlscan\URLSCAN.INI文件进行修改,
原为
AllowHighBitCharacters=0      ; if 1, allow high bit (ie. UTF8 or MBCS) characters in URL
改为
AllowHighBitCharacters=1       ; if 1, allow high bit (ie. UTF8 or MBCS) characters in URL

  重新启动IISADMIN。

XREA空间去广告

建个文件名" .htaccess"的文件, 文件内容如下:
LayoutIgnoreURI *.
LayoutIgnoreURI *.cgi
LayoutIgnoreURI *.htm
LayoutIgnoreURI *.html
将.htaccess上传至Xrea空间的Public_html目录下,即可去掉广告!

注意 *.* 这里..想去那种扩展名的文件,就写上那种文件的扩展名! 这个是最简单的方法,只要在根目录加这个文件,那么整个网站都不会有广告!

帝国 下载不采用弹出窗口式

下载不采用弹出窗口式说明
如果不采用弹出式下载的话,可依以下步骤完成:

1.修改下载地址模板("公共模板" -> "修改下载地址模板"):
将:
[ <a href=#edown onclick="window.open(‘[!–down.url–]’,”,’width=300,height=300′);">[!–down.name–]</a> ]
改成:
[ <a href="/e/DownSys/GetDown?classid=[!–classid–]&id=[!–id–]&pathid=[!–pathid–]">[!–down.name–]</a> ]
(如果发现不支持[!–classid–]与[!–id–]标签,重新下载安装程序,把里面的e/class/functions.php复制到本地即可支持)

2.开启直接下载开关:
修改e/DownSys/GetDown/index.php文件,把
-------------------
//———-开启自动链接
$openthisdown=1;//1为关闭,0为开启
-------------------
设置一下

3.重新刷新下载表的页面即可(记得选择重复刷新)

此方案缺点:起不到防盗链作用,如果你服务器本身就有防盗效果,才推荐使用此方式.
 

浮动广告 鼠标移到广告条后出现大图片的代码

<script language=’javascript’>
document.write(‘<div id="mylayer" style="position:absolute; left:260px; top:80px; z-index:1">’);
document.write("<a href=’http://www.maqie.com’ target=’_blank’ onMouseOut=’document.all.chan.src=\"/host.gif\";document.all.chan.width=100;document.all.chan.height=100;’ onMouseOver=’document.all.chan.src=\"/ad2.gif\";document.all.chan.width=236;document.all.chan.height=211;’><img border=0 name=chan src=’/host.gif’width=100 height=100></a> ");
document.write(‘</div>’);

self.onError=null;    currentX = currentY = 0;  
        whichIt = null;           
        lastScrollX = 0; lastScrollY = 0;
        NS = (document.layers) ? 1 : 0;
        IE = (document.all) ? 1: 0;
        <!– STALKER CODE –>
        function heartBeat() {
            if(IE) { diffY = document.body.scrollTop; diffX = document.body.scrollLeft; }
            if(NS) { diffY = self.pageYOffset; diffX = self.pageXOffset; }
            if(diffY != lastScrollY) {
                        percent = .1 * (diffY – lastScrollY);
                        if(percent > 0) percent = Math.ceil(percent);
                        else percent = Math.floor(percent);
                        if(IE) document.all.mylayer.style.pixelTop += percent;
                        if(NS) document.mylayer.top += percent; 
                        lastScrollY = lastScrollY + percent;
            }
            if(diffX != lastScrollX) {
                percent = .1 * (diffX – lastScrollX);
                if(percent > 0) percent = Math.ceil(percent);
                else percent = Math.floor(percent);
                if(IE) document.all.mylayer.style.pixelLeft += percent;
                if(NS) document.mylayer.left += percent;
                lastScrollX = lastScrollX + percent;
            }    
        }
        <!– /STALKER CODE –>
        <!– DRAG DROP CODE –>
        function checkFocus(x,y) { 
                stalkerx = document.mylayer.pageX;
                stalkery = document.mylayer.pageY;
                stalkerwidth = document.mylayer.clip.width;
                stalkerheight = document.mylayer.clip.height;
                if( (x > stalkerx && x < (stalkerx+stalkerwidth)) && (y > stalkery && y < (stalkery+stalkerheight))) return true;
                else return false;
        }
        function grabIt(e) {
            if(IE) {
                whichIt = event.srcElement;
                while (whichIt.id.indexOf("mylayer") == -1) {
                    whichIt = whichIt.parentElement;
                    if (whichIt == null) { return true; }
                }
                whichIt.style.pixelLeft = whichIt.offsetLeft;
                whichIt.style.pixelTop = whichIt.offsetTop;
                currentX = (event.clientX + document.body.scrollLeft);
                   currentY = (event.clientY + document.body.scrollTop);     
            } else { 
                window.captureEvents(Event.MOUSEMOVE);
                if(checkFocus (e.pageX,e.pageY)) { 
                        whichIt = document.mylayer;
                        StalkerTouchedX = e.pageX-document.mylayer.pageX;
                        StalkerTouchedY = e.pageY-document.mylayer.pageY;
                } 
            }
            return true;
        }
        function moveIt(e) {
            if (whichIt == null) { return false; }
            if(IE) {
                newX = (event.clientX + document.body.scrollLeft);
                newY = (event.clientY + document.body.scrollTop);
                distanceX = (newX – currentX);    distanceY = (newY – currentY);
                currentX = newX;    currentY = newY;
                whichIt.style.pixelLeft += distanceX;
                whichIt.style.pixelTop += distanceY;
                if(whichIt.style.pixelTop < document.body.scrollTop) whichIt.style.pixelTop = document.body.scrollTop;
                if(whichIt.style.pixelLeft < document.body.scrollLeft) whichIt.style.pixelLeft = document.body.scrollLeft;
                if(whichIt.style.pixelLeft > document.body.offsetWidth – document.body.scrollLeft – whichIt.style.pixelWidth – 20) whichIt.style.pixelLeft = document.body.offsetWidth – whichIt.style.pixelWidth – 20;
                if(whichIt.style.pixelTop > document.body.offsetHeight + document.body.scrollTop – whichIt.style.pixelHeight – 5) whichIt.style.pixelTop = document.body.offsetHeight + document.body.scrollTop – whichIt.style.pixelHeight – 5;
                event.returnValue = false;
            } else { 
                whichIt.moveTo(e.pageX-StalkerTouchedX,e.pageY-StalkerTouchedY);
                if(whichIt.left < 0+self.pageXOffset) whichIt.left = 0+self.pageXOffset;
                if(whichIt.top < 0+self.pageYOffset) whichIt.top = 0+self.pageYOffset;
                if( (whichIt.left + whichIt.clip.width) >= (window.innerWidth+self.pageXOffset-17)) whichIt.left = ((window.innerWidth+self.pageXOffset)-whichIt.clip.width)-17;
                if( (whichIt.top + whichIt.clip.height) >= (window.innerHeight+self.pageYOffset-17)) whichIt.top = ((window.innerHeight+self.pageYOffset)-whichIt.clip.height)-17;
                return false;
            }
            return false;
        }
        function dropIt() {
            whichIt = null;
            if(NS) window.releaseEvents (Event.MOUSEMOVE);
            return true;
        }
        <!– DRAG DROP CODE –>
        if(NS) {
            window.captureEvents(Event.MOUSEUP|Event.MOUSEDOWN);
            window.onmousedown = grabIt;
             window.onmousemove = moveIt;
            window.onmouseup = dropIt;
        }
        if(IE) {
            document.onmousedown = grabIt;
             document.onmousemove = moveIt;
            document.onmouseup = dropIt;
        }
        if(NS || IE) action = window.setInterval("heartBeat()",1);
</script>
 

漂浮图片广告代码

<html>
<head>
</head>
<body>
<div id="img" style="position:absolute;; width: 200; height: 151"><a href="http://"><img src="1.jpg" border="0"></a></div>
a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>

<script LANGUAGE="JavaScript">
var xPos = 20;
var yPos = 10;
img.style.left= xPos;
img.style.top = yPos;
var step = 1;
var delay = 30;
var width,height,Hoffset,Woffset;
var y = 1;
var x = 1;
var interval;
img.visibility = "visible";
function changePos()
{
width = document.body.clientWidth;
height = document.body.clientHeight;
Hoffset = img.offsetHeight;
Woffset = img.offsetWidth;
if (y)
{
yPos = yPos + step;
}
else
{
yPos = yPos – step;
}
if (yPos < 0)
{
y = 1;
yPos = 0;
}
if (yPos >= (height – Hoffset))
{
y = 0;
yPos = (height – Hoffset);
}
if (x)
{
xPos = xPos + step;
}
else
{
xPos = xPos – step;
}
if (xPos < 0)
{
x = 1;
xPos = 0;
}
if (xPos >= (width – Woffset))
{
x = 0;
xPos = (width – Woffset);
}
img.style.left = xPos + document.body.scrollLeft;
img.style.top = yPos + document.body.scrollTop;
}
function start()
{
interval = setInterval(‘changePos()’, delay);
}
function pause_resume()
{
clearInterval(interval);
}
start();
</script>
</body>
</html>

 <div id="ad" style="position:absolute"><a href="http://www.maqie.com" target="_blank"><img src="fwd.gif" width="200" height="87" border="0"></a></div>
<script>
var x = 50,y = 60 //浮动层的初始位置,分别对应层的初始X坐标和Y坐标
var xin = true, yin = true //判断层的X坐标和Y坐标是否在在控制范围之内,xin为真是层向右移动,否则向左;yin为真是层向下移动,否则向上
var step = 1 //层移动的步长,值越大移动速度越快
var delay = 10 //层移动的时间间隔,单位为毫秒,值越小移动速度越快
var obj=document.getElementById("ad") //捕获id为ad的层作为漂浮目标
function floatAD() {
var L=T=0 //层移动范围的左边界(L)和上边界(T)坐标
var R= document.body.clientWidth-obj.offsetWidth //层移动的右边界
var B = document.body.clientHeight-obj.offsetHeight //层移动的下边界
obj.style.left = x + document.body.scrollLeft //更新层的X坐标,实现X轴方向上的运动;document.body.scrollLeft为文档区域的滚动条向右拉的距离,以保证在滚动条右拉时层仍在可见范围内
obj.style.top = y + document.body.scrollTop //更新层的Y坐标,实现Y轴方向上的运动;document.body.scrollTop为文档区域的滚动条向下拉的距离,以保证在滚动条下拉时层仍在可见范围内
x = x + step*(xin?1:-1) //通过判断层的范围决定层在X轴上的运动方向
if (x < L) { xin = true; x = L} //层超出左边界时的处理
if (x > R){ xin = false; x = R} //层超出右边界时的处理
y = y + step*(yin?1:-1) //通过判断层的范围决定层在Y轴上的运动方向
if (y < T) { yin = true; y = T } //层超出上边界时的处理
if (y > B) { yin = false; y = B } //层超出下边界时的处理
}
var itl= setInterval("floatAD()", delay) //每delay秒执行一次floatAD函数
obj.onmouseover=function(){clearInterval(itl)} //层在鼠标移上时清除上面的间隔事件,实现层在的鼠标移上时停止运动的效果
obj.onmouseout=function(){itl=setInterval("floatAD()", delay)} //层在鼠标移开时开始间隔事件,实现层在的鼠标移开时继续运动的效果
</script>

 

<div id="img" style="position:absolute;; width: 200; height: 151"><a href="http://"><img src="1.jpg" border="0"></a></div>

这个为图片广告属性。

怎么样控制CSS <BR> <br /> 的高度,或者使其失效

    网上找了好多资料,CSS基本都BR 不起作用,如果是 <P> 之类的话就好控制了。再浏览器中,要取消<BR>的作用,好像貌似只有用 javascript 替换。或者服务端输出的时候就替换掉。

后来找到一个CSS中可以起作用的,直接

br{
display:inline; line-height:110px;
}

br{
line-height:110px;
}

后面的方法,再FIREFOX 下 同样有作用