DDOS Deflate 脚本 – 利用 Iptables 或 SPF 防范攻击

一个很有效的、通过Advanced Policy Firewall (APF) 或者 iptables 防止DDOS攻击的脚本:
(D)DoS Deflate

安装方法
wget http://www.inetbase.com/scripts/ddos/install.sh
chmod 0700 install.sh
./install.sh

安装后,脚本会每分钟运行一次,屏蔽的IP地址10分钟后自动解封。
这些参数也可以在配置文件 /usr/local/ddos/ddos.conf 中修改

设置永不屏蔽的IP地址白名单 /usr/local/ddos/ignore.ip.list

DDOS Deflate 的目前版本是 0.6,在我测试的 centos 上运行时不能正常解析出IP地址

修复方法
打开脚本文件 /usr/local/ddos/ddos.sh

修改原来的代码:
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n

替换为
netstat -ntu | grep ':' | awk '{print $5}' | awk '{sub("::ffff:","");print}' | cut -f1 -d ':' | sort | uniq -c | sort -nr

备注:安装ddos deflate后,在系统的cron job里,会自动加上了命令 /usr/local/ddos/ddos.sh >/dev/null 2>&1

生成启用、禁止和删除外部关键字约束的SQL脚本

利用主关键字表来自动生成:启用、禁止和删除数据表中外部关键字约束的SQL脚本

源代码:

-- Enable, Disable, Drop and Recreate FKs based on Primary Key table  
-- Written 2007-11-18  
-- Edgewood Solutions / MSSQLTips.com  
-- Works for SQL Server 2005  

SET NOCOUNT ON  

DECLARE @operation VARCHAR(10)  
DECLARE @tableName sysname  
DECLARE @schemaName sysname  

SET @operation = 'DROP' --ENABLE, DISABLE, DROP  
SET @tableName = 'SpecialOfferProduct'  
SET @schemaName = 'Sales'  

DECLARE @cmd NVARCHAR(1000) 

DECLARE   
   @FK_NAME sysname,  
   @FK_OBJECTID INT,  
   @FK_DISABLED INT,  
   @FK_NOT_FOR_REPLICATION INT,  
   @DELETE_RULE    smallint,     
   @UPDATE_RULE    smallint,     
   @FKTABLE_NAME sysname,  
   @FKTABLE_OWNER sysname,  
   @PKTABLE_NAME sysname,  
   @PKTABLE_OWNER sysname,  
   @FKCOLUMN_NAME sysname,  
   @PKCOLUMN_NAME sysname,  
   @CONSTRAINT_COLID INT  


DECLARE cursor_fkeys CURSOR FOR   
   SELECT  Fk.name,  
           Fk.OBJECT_ID,   
           Fk.is_disabled,   
           Fk.is_not_for_replication,   
           Fk.delete_referential_action,   
           Fk.update_referential_action,   
           OBJECT_NAME(Fk.parent_object_id) AS Fk_table_name,   
           schema_name(Fk.schema_id) AS Fk_table_schema,   
           TbR.name AS Pk_table_name,   
           schema_name(TbR.schema_id) Pk_table_schema  
   FROM    sys.foreign_keys Fk LEFT OUTER JOIN   
           sys.tables TbR ON TbR.OBJECT_ID = Fk.referenced_object_id --inner join   
   WHERE   TbR.name = @tableName  
           AND schema_name(TbR.schema_id) = @schemaName  

OPEN cursor_fkeys  

FETCH NEXT FROM   cursor_fkeys   
   INTO @FK_NAME,@FK_OBJECTID,  
       @FK_DISABLED,  
       @FK_NOT_FOR_REPLICATION,  
       @DELETE_RULE,     
       @UPDATE_RULE,     
       @FKTABLE_NAME,  
       @FKTABLE_OWNER,  
       @PKTABLE_NAME,  
       @PKTABLE_OWNER  

WHILE @@FETCH_STATUS = 0   
BEGIN   

   -- create statement for enabling FK  
   IF @operation = 'ENABLE'   
   BEGIN  
       SET @cmd = 'ALTER TABLE [' + @FKTABLE_OWNER + '].[' + @FKTABLE_NAME   
           + ']  CHECK CONSTRAINT [' + @FK_NAME + ']'  

      PRINT @cmd  
   END  

   -- create statement for disabling FK  
   IF @operation = 'DISABLE'  
   BEGIN     
       SET @cmd = 'ALTER TABLE [' + @FKTABLE_OWNER + '].[' + @FKTABLE_NAME   
           + ']  NOCHECK CONSTRAINT [' + @FK_NAME + ']'  

      PRINT @cmd  
   END  

   -- create statement for dropping FK and also for recreating FK  
   IF @operation = 'DROP'  
   BEGIN  

       -- drop statement  
       SET @cmd = 'ALTER TABLE [' + @FKTABLE_OWNER + '].[' + @FKTABLE_NAME   
       + ']  DROP CONSTRAINT [' + @FK_NAME + ']'     

      PRINT @cmd  

       -- create process  
       DECLARE @FKCOLUMNS VARCHAR(1000), @PKCOLUMNS VARCHAR(1000), @COUNTER INT  

       -- create cursor to get FK columns  
       DECLARE cursor_fkeyCols CURSOR FOR   
       SELECT  COL_NAME(Fk.parent_object_id, Fk_Cl.parent_column_id) AS Fk_col_name,   
               COL_NAME(Fk.referenced_object_id, Fk_Cl.referenced_column_id) AS Pk_col_name  
       FROM    sys.foreign_keys Fk LEFT OUTER JOIN   
               sys.tables TbR ON TbR.OBJECT_ID = Fk.referenced_object_id INNER JOIN   
               sys.foreign_key_columns Fk_Cl ON Fk_Cl.constraint_object_id = Fk.OBJECT_ID   
       WHERE   TbR.name = @tableName  
               AND schema_name(TbR.schema_id) = @schemaName  
               AND Fk_Cl.constraint_object_id = @FK_OBJECTID -- added 6/12/2008  
       ORDER BY Fk_Cl.constraint_column_id  

       OPEN cursor_fkeyCols  

       FETCH NEXT FROM    cursor_fkeyCols INTO @FKCOLUMN_NAME,@PKCOLUMN_NAME  

       SET @COUNTER = 1  
       SET @FKCOLUMNS = ''  
       SET @PKCOLUMNS = ''  
         
       WHILE @@FETCH_STATUS = 0   
       BEGIN   

           IF @COUNTER > 1   
           BEGIN  
               SET @FKCOLUMNS = @FKCOLUMNS + ','  
               SET @PKCOLUMNS = @PKCOLUMNS + ','  
           END  

           SET @FKCOLUMNS = @FKCOLUMNS + '[' + @FKCOLUMN_NAME + ']'  
           SET @PKCOLUMNS = @PKCOLUMNS + '[' + @PKCOLUMN_NAME + ']'  

           SET @COUNTER = @COUNTER + 1  
             
           FETCH NEXT FROM    cursor_fkeyCols INTO @FKCOLUMN_NAME,@PKCOLUMN_NAME  
       END  

       CLOSE cursor_fkeyCols   
       DEALLOCATE cursor_fkeyCols   

       -- generate create FK statement  
       SET @cmd = 'ALTER TABLE [' + @FKTABLE_OWNER + '].[' + @FKTABLE_NAME + ']  WITH ' +   
           CASE @FK_DISABLED   
               WHEN 0 THEN ' CHECK '  
               WHEN 1 THEN ' NOCHECK '  
           END +  ' ADD CONSTRAINT [' + @FK_NAME   
           + '] FOREIGN KEY (' + @FKCOLUMNS   
           + ') REFERENCES [' + @PKTABLE_OWNER + '].[' + @PKTABLE_NAME + '] ('   
           + @PKCOLUMNS + ') ON UPDATE ' +   
           CASE @UPDATE_RULE   
               WHEN 0 THEN ' NO ACTION '  
               WHEN 1 THEN ' CASCADE '   
               WHEN 2 THEN ' SET_NULL '   
               END + ' ON DELETE ' +   
           CASE @DELETE_RULE  
               WHEN 0 THEN ' NO ACTION '   
               WHEN 1 THEN ' CASCADE '   
               WHEN 2 THEN ' SET_NULL '   
               END + '' +  
           CASE @FK_NOT_FOR_REPLICATION  
               WHEN 0 THEN ''  
               WHEN 1 THEN ' NOT FOR REPLICATION '  
           END  

      PRINT @cmd  

   END  

   FETCH NEXT FROM    cursor_fkeys   
      INTO @FK_NAME,@FK_OBJECTID,  
           @FK_DISABLED,  
           @FK_NOT_FOR_REPLICATION,  
           @DELETE_RULE,     
           @UPDATE_RULE,     
           @FKTABLE_NAME,  
           @FKTABLE_OWNER,  
           @PKTABLE_NAME,  
           @PKTABLE_OWNER  
END  

CLOSE cursor_fkeys   
DEALLOCATE cursor_fkeys  

测试数据库:AdventureWorks

实例一:
Table: SpecialOfferProduct
Schema: Sales
Operation: DROP

输出:

ALTER TABLE [Sales].[SalesOrderDetail] DROP CONSTRAINT [FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID]
ALTER TABLE [Sales].[SalesOrderDetail] WITH NOCHECK ADD CONSTRAINT [FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID] FOREIGN KEY ([SpecialOfferID],[ProductID]) REFERENCES [Sales].[SpecialOfferProduct] ([SpecialOfferID],[ProductID]) ON UPDATE NO ACTION ON DELETE NO ACTION

实例二:
Table: SpecialOfferProduct
Schema: Sales
Operation: DISABLE

输出:

ALTER TABLE [Sales].[Individual] NOCHECK CONSTRAINT [FK_Individual_Contact_ContactID]
ALTER TABLE [Sales].[SalesOrderHeader] NOCHECK CONSTRAINT [FK_SalesOrderHeader_Contact_ContactID]

ALTER TABLE [Sales].[StoreContact] NOCHECK CONSTRAINT [FK_StoreContact_Contact_ContactID]

ALTER TABLE [Purchasing].[VendorContact] NOCHECK CONSTRAINT [FK_VendorContact_Contact_ContactID]

ALTER TABLE [Sales].[ContactCreditCard] NOCHECK CONSTRAINT [FK_ContactCreditCard_Contact_ContactID]

ALTER TABLE [HumanResources].[Employee] NOCHECK CONSTRAINT [FK_Employee_Contact_ContactID]

在Twitter上自动更新产品

下面的一段PHP代码,用于实现在zen cart网店后台添加新产品后,自动在twitter上发布关于该产品的信息。
(通常是加入 /admin/includes/modules/update_product.php 这个文件)

// BOF twitter feed
    
    if ($action == 'insert_product')
    {
      $purl = zen_catalog_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products_id);
      $tinyPurl = file_get_contents('http://tinyurl.com/api-create.php?url='.$purl);
      function updateStatus($user, $password, $message)
      {
        $url = "http://twitter.com/statuses/update.xml";
        $curl = curl_init($url);
        $data = array('status'=>$message);
        curl_setopt($curl, CURLOPT_USERPWD, $user.':'.$password);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:'));
        $result = @curl_exec($curl);
        curl_close($curl);
        return $result;
      }
      $message = STORE_NAME . ' has a new product. ' . $tinyPurl;
      $user = 'YYYYYYYYY';
      $password = 'XXXXXXXXX';
      $result = updateStatus($user, $password, $message);
      $messageStack->add_session($result, 'error');
    }
    // EOF twitter feed

通过SecureCRT访问亚马逊Amazon EC2主机

亚马逊推出了免费的云主机服务器 Amazon EC2,它是通过安全密钥来访问主机的。问题是下载的密钥在SecureCRT 上无法直接使用,需要转换。
下面的方法可以在自己的linux主机上生成securecrt需要的密钥。

首先在 AWS 管理面板中生成密钥对。
将密钥上传到一台自己的linux主机,下面举例文件名为 amazon-ec2-key.pem

修改亚马逊提供的密钥文件权限:
chmod og-r amazon-ec2-key.pem

改写密钥格式为 OpenSSH,如果询问passphrase可以留空(直接回车)
ssh-keygen -p -f amazon-ec2-key.pem

生成公密钥 .pub 文件。使用公密钥时,SecureCRT会询问私密钥或者.pem文件
ssh-keygen -e -f amazon-ec2-key.pem >> amazon-ec2-key.pem.pub

现在可以在 SecureCRT 中使用刚生成的公密钥了,连接到亚马逊的主机也无需再输入密码。

在CentOS上升级PCRE

PCRE – Perl Compatible Regular Expressions

今天在服务器上安装微博,出现错误:

PHP is linked to a version of the PCRE library that does not support Unicode properties. If you are running Red Hat Enterprise Linux / CentOS 5.4 or earlier, see our documentation page on fixing this.

但我的服务器已经是 CentOS 5.5 了

登录服务器检查:

# pcretest -C
PCRE version 6.6 06-Feb-2006
Compiled with
UTF-8 support
No Unicode properties support
Newline character is LF
Internal link size = 2
POSIX malloc threshold = 10
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack

果然PCRE库不支持 unicode 属性。
重新下载了最新版的 PCRE库,运行

./configure –prefix=/usr –enable-utf8 –enable-unicode-properties
make
make install

再次检查系统:

# pcre-config –version
8.10

看起来好像成功了。但是,

# pcretest -C
PCRE version 6.6 06-Feb-2006
Compiled with
UTF-8 support
No Unicode properties support
Newline character is LF
Internal link size = 2
POSIX malloc threshold = 10
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack

怎么还是 6.6 的旧版本?pcre-config 和 pcretest 显示的版本竟然会不一样。

上网Google了很久,才发现问题的根源:

原来在 /lib/ 目录库中还有两个不同的版本

# locate libpcre
> > /lib/libpcre.so.0
> > /lib/libpcre.so.0.0.1
> > /usr/lib/libpcre.a
> > /usr/lib/libpcre.la
> > /usr/lib/libpcre.so
> > /usr/lib/libpcre.so.0

先 unlink /lib/libpcre.so.0
再将 /lib/libpcre.so.0.0.1 改个名字,问题解决

# pcretest -C
PCRE version 8.10 2010-06-25
Compiled with
UTF-8 support
Unicode properties support
Newline sequence is LF
\R matches all Unicode newlines
Internal link size = 2
POSIX malloc threshold = 10
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack