Rootop 服务器运维与web架构

2011-03-10
发表者 Venus
暂无评论

Linux/Unix下ODBC的安装、配置与编程

ODBC原理

ODBC 是Open Database Connect 即开放数据库互连的简称,它是由Microsoft 公司于1991 年提出的一个用于访问数据库的统一界面标准,是应用程序和数据库系统之间的中间件。它通过使用相应应用平台上和所需数据库对应的驱动程序与应用程序的交互来实现对数据库的操作,避免了在应用程序中直接调用与数据库相关的操作,从而提供了数据库的独立性。

ODBC 主要由驱动程序和驱动程序管理器组成。驱动程序是一个用以支持ODBC 函数调用的模块,每个驱动程序对应于相应的数据库,当应用程序从基于一个数据库系统移植到另一个时,只需更改应用程序中由ODBC 管理程序设定的与相应数据库系统对应的别名即可。驱动程序管理器可链接到所有ODBC 应用程序中,它负责管理应用程序中ODBC 函数与DLL 中函数的绑定。

ODBC 使用层次的方法来管理数据库,在数据库通信结构的每一层,对可能出现依赖数据库产品自身特性的地方,ODBC 都引入一个公共接口以解决潜在的不一致性,从而很好地解决了基于数据库系统应用程序的相对独立性,这也是ODBC 一经推出就获得巨大成功的重要原因之一。

从结构上分,ODBC 分为单束式和多束式两类。

  1. 单束式驱动程序
    单束式驱动程序介于应用程序和数据库之间,像中介驱动程序一样数据提供一个统一的数据访问方式。 当用户进行数据库操作时,应用程序传递一个ODBC 函数调用给ODBC 驱动程序管理器,由ODBC API 判断该调用是由它直接处理并将结果返回还是送交驱动程序执行并将结果返回。 由上可见,单束式驱动程序本身是一个数据库引擎,由它直接可完成对数据库的操作,尽管该数据库可能位于网络的任何地方。
  2. 多束式驱动程序
    多束式驱动程序负责在数据库引擎和客户应用程序之间传送命令和数据,它本身并不执行数据处理操作而用于远程操作的网络通信协议的一个界面。 前端应用程序提出对数据库处理的请求,该请求转给ODBC 驱动程序管理器,驱动程序管理器依据请求的情况,就地完成或传给多束驱动程序,多束式驱动程序将请求翻译为特定厂家的数据库通信接口(如Oracle 的SQLNet)所能理解的形式并交于接口去处理,接口把请求经网络传送给服务器上的数据引擎,服务器处理完后把结果发回给数据库通信接口,数据库接口将结果传给多束式ODBC 驱动程序,再由驱动程序将结果传给应用程序。

很多程序员已经体会到了在Windows平台下的ODBC的益处,而在Linux/Unix下进行数据库编程的时候却不得不根据不同的数据库来选择特有的API进行编程,一旦数据库发生了改变,所有与这些API相关的程序都必须进行修改。其实在Linux/Unix下现在也有了自己的ODBC,可以使我们的数据库编程就像在Windows平台下一样简单。

下面我们开始介绍Linux/Unix下的ODBC:

回页首

Linux/UnixODBC的安装

方法一:
先下载最新的unixODBC源码包( http://www.unixodbc.org/unixODBC-2.2.1.tar.gz)放到/usr/local下,然后运行下述命令:

tar zxvf unixODBC-2.2.1.tar.gz

cd unixODBC-2.2.1

./configure –prefix=/usr/local/unixODBC-2.2.1 –includedir=/usr/include

–libdir=/usr/lib -bindir=/usr/bin –sysconfdir=/etc

make

make install

安装成功后,unixODBC所需的头文件都被安装到了/usr/inlucde下,编译好的库文件安装到了/usr/lib下,与unixODBC相关的可执行文件安装到了/usr/bin下,配置文件放到了/etc下。

方法二:
下载rpm包进行安装,我们这里以Red Hat 7.3为例:
unixODBC-2.2.0-5 RPM for i386(安装包及源码包)
( ftp://speakeasy.rpmfind.net/linux/redhat/7.3/en/os/i386/RedHat/RPMS/unixODBC-2.2.0-5.i386.rpmftp://ftp.rpmfind.net/linux/redhat/7.3/en/os/i386/SRPMS/unixODBC-2.2.0-5.src.rpm
unixODBC-devel-2.2.0-5 RPM for i386
( ftp://speakeasy.rpmfind.net/linux/redhat/7.3/en/os/i386/RedHat/RPMS/unixODBC-devel-2.2.0-5.i386.rpm
直接将unixODBC-2.2.0-5.i386.rpm和unixODBC-devel-2.2.0-5.i386.rpm装入系统就可以了,命令如下:

rpm -ivh unixODBC-2.2.0-5.i386.rpm

rpm -ivh unixODBC-devel-2.2.0-5.i386.rpm

安装好以后,所需的各个部分与上面所列的位置相同。

回页首

Linux/UnixODBC的配置

运行ODBCConfig程序(在/usr/bin下),如下图:
图一:ODBCConfig主窗口

和Windows下的ODBC设置窗口是不是很像?我想大家都能看懂吧。

第一步:安装数据库的ODBC驱动程序
Drivers这一栏中用来设置数据库的驱动程序,点击Add按钮,会出现下图:
图二:ODBCConfig Driver Properties窗口

Name一栏填入数据库驱动的名称,Description是数据库驱动的描述,Driver是用来选择数据库驱动程序的,Setup是用来选择数据库驱动安装程序的,如果你是按照上述安装方法安装的,这些程序都放在/usr/lib下,下面是数据库驱动程序的列表:

数据库 数据库驱动程序 数据库驱动安装程序
TXT libodbctxt.so libodbctxtS.so
NNTP libnn.so libodbcnnS.so
MiniSQL libodbcmini.so libodbcminiS.so
PostgreSQL libodbcpsql.so libodbcpsqlS.so
MySQL (注释) libodbcmyS.so
Sybase/MS SQL (注释) libtdsS.so
Oracle (注释) liboraodbcS.so

注释:
MySQL、Sybase/MS SQL和Oracle的数据库驱动可以在下列网址找到:
MySQL           http://www.unixodbc.org/myodbc.html
Sybase/MS SQL       http://www.freetds.org
Oracle           http://www.easysoft.org

MySQL的驱动程序MyODBC-2.50.39-4 RPM for i386以及源码包:
ftp://speakeasy.rpmfind.net/linux/redhat/7.3/en/os/i386/RedHat/RPMS/MyODBC-2.50.39-4.i386.rpm
ftp://ftp.redhat.com/pub/redhat/linux/7.3/en/os/i386/SRPMS/MyODBC-2.50.39-4.src.rpm

选择好驱动程序之后,点击”√”保存退出。

第二步:设置DSN
DSN分为User DSN、System DSN和File DSN三种,我们以System DSN为例。选中System DSN一栏以后,点击Add…按钮就会见到下图:
图三:创建DSN选择数据库驱动

列表中会列出你已经安装好的数据库驱动程序,我这里只装了MySQL和PostgreSQL,然后选择你所要使用的驱动程序,然后点击OK就会出现下图:
图四:DSN的设置

我这里使用的是MySQL的数据库驱动,不同的数据库,这个窗口的内容会有所不同。Name是数据源的名称,Description是描述,Server可以选择服务器,如果本机启动了MySQL就可以选择localhost,如果Port和Socket有特殊要求,再根据实际情况进行修改,Database是用来选择数据库的,下拉菜单不一定包含所有的数据库,你可以把自己已经创建好的数据库名称填写在这里。都配置好之后,点击”√”保存退出。

这样Linux/Unix下的ODBC数据源就已经设置好了,大家还可以在ODBCConfig程序的Status栏中查看ODBC的使用情况,在Advanced栏中设置是否做日志或者启动连接池,在About栏中,有一个Linux/Unix ODBC的示意图,在Credits按钮中可以看到所有开发者的名字的列表。 ODBCConfig程序中所有有关数据库驱动程序的信息被放在odbcinst.ini(在/etc下)文件中,有关DSN的信息被放在odbc.ini(在/etc下)文件中,大家有兴趣的话,可以自己去观察一下。

第三步:使用DataManager程序浏览数据库
运行DataManager程序之后就可以查看Drivers、System DSN和User DSN这几项内容,,在浏览数据库的时候,可以在右面的SQL栏中输入SQL语句,然后点击人形按钮就可以运行SQL语句,运行结果会在Results一栏中显示出来,具体情况可以见下图:
图五:使用DataManager浏览数据库

第四步:使用isql程序查看数据库
unixODBC还提供了命令台下查看数据库的程序,这就是isql,用法如下:

isql DSN [UID [PWD]] [options]

DSN            数据源名称

UID            用户ID

PWD            用户密码

Options:

-b             批处理,没有提示符的模式

-dx            设置列之间的分隔符为x

-w             将查询结果输出为HTML格式

-c             第一行输出列名

–version                 输出isql的版本号

回页首

Linux/UnixODBC的编程

1、使用unixODBC提供的ODBC API进行编程:
在进行编程之前,我们来看一下ODBC API中的常用数据类型与我们在C语言中使用的数据类型的对应关系:

类型标识符 ODBC数据类型 C数据类型
SQL_C_CHAR SQLCHAR * unsigned char *
SQL_C_SSHORT SQLSMALLINT short int
SQL_C_USHORT SQLUSMALLINT unsigned short int
SQL_C_SLONG SQLINTEGER long int
SQL_C_FLOAT SQLREAL float
SQL_C_DOUBLE SQLDOUBLE, SQLFLOAT double
SQL_C_BINARY SQLCHAR * unsigned char *
SQL_C_TYPE_DATE SQL_DATE_STRUCT struct tagDATE_STRUCT {SQLSMALLINT year; SQLUSMALLINT month; SQLUSMALLINT day; } DATE_STRUCT;
SQL_C_TYPE_TIME SQL_TIME_STRUCT struct tagTIME_STRUCT {SQLUSMALLINT hour; SQLUSMALLINT minute; SQLUSMALLINT second; } TIME_STRUCT;

我们这里使用的数据库名称为test(DSN),这个DSN使用的用户名是root,密码为空,表的名称是web,字段情况如下:

字段名 数据类型
id integer
name char(40)
size integer

第一:设定ODBC环境句柄并设置参数
首先我们需要声明一个ODBC环境句柄(SQLHENV),它可以用来获得有关的ODBC环境信息,我们需要调用SQLAllocHandle ( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &V_OD_Env )来获得这个句柄,V_OD_Env就是要分配的SQLHENV类型的环境句柄。 分配好句柄之后,你给它需要设定所使用的ODBC版本,你可以调用SQLSetEnvAttr ( V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0 ),SQL_ATTR_ODBC_VERSION是存放你定义的ODBC版本号的变量,SQL_OV_ODBC3则说明你的程序使用的是ODBC 3.0。

第二:设定连接句柄并设置超时参数
我们需要声明一个连接句柄(SQLHDBC),用来存放数据库连接信息的,调用SQLAllocHandle ( SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc )获得连接句柄,V_OD_hdbc就是要分配的SQLHDBC类型的连接句柄。 分配好之后,我们可以调用SQLSetConnectAttr ( V_OD_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0 )来设定连接超时参数。

第三:连接数据库
调用SQLConnect ( V_OD_hdbc, (SQLCHAR*) “Test”, SQL_NTS, (SQLCHAR*) “root”, SQL_NTS, (SQLCHAR*) “”, SQL_NTS )连接我前面提到的数据库,需要设定三个参数,就是数据库名称、用户名和密码(因为我的数据库密码为空,所以这里的密码也为空),后面的SQL_NTS的位置应该写入这些参数的长度,如果写的是SQL_NTS就是让SQLConnect来决定参数的长度。

第四:分配SQL语句的句柄并进行查询:
需要声明一个SQL语句的句柄(SQLHSTMT),用来存放SQL语句信息的,调用SQLAllocHandle ( SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt )来获得这个句柄,V_OD_hstmt就是我们要分配的SQLHSTMT类型的SQL语句句柄。

我们的查询语句是:

SELECT name, id FROM web ORDER BY id

执行这条查询语句之后,查询结果可能有很多行,但每行只有两列,分别对应name和id,它们的数据类型为integer和char*,在ODBC中的数据类型标识符为SQL_C_ULONG和SQL_C_CHAR。我们需要先声明这样的两个变量来存贮查询结果:

SQLINTEGER                V_OD_id;

char             V_OD_buffer[200];

然后我们需要使用SQLBindCol函数把查询结果和我们定义的变量进行绑定:

SQLBindCol(V_OD_hstmt,1,SQL_C_CHAR, &V_OD_buffer,150,&V_OD_err);

SQLBindCol(V_OD_hstmt,2,SQL_C_ULONG,&V_OD_id,150,&V_OD_err);

这里的V_OD_err是用来存放错误信息编号的变量,类型也是SQLINTEGER。
接下来,我们调用SQLExecDirect来进行查询:

SQLExecDirect ( V_OD_hstmt, “SELECT dtname,iduser FROM web order by iduser”, SQL_NTS );

我们可以用SQLNumResultCols ( V_OD_hstmt, &V_OD_colanz )来获得结果的列数,也可以用SQLRowCount( V_OD_hstmt, &V_OD_rowanz )来获得结果的条数,V_OD_colanz和V_OD_rowanz分别存储相应的结果,类型分别为SQLSMALLINT和SQLINTEGER。
在读取结果之前,我们需要调用SQLFetch ( V_OD_hstmt )语句,这个语句可以用来获得第一条结果也可以用来都下一条,有点像next的感觉。然后我们就可以在V_OD_id和V_OD_buffer里面获得每条记录的结果了。

第五:关于关闭连接和释放句柄
关闭数据库的连接,调用SQLDisconnect ( V_OD_hdbc )就可以了,但在关闭数据库之前需要先释放SQL语句的句柄,而且在关闭数据库之后应该释放连接句柄和ODBC环境句柄,语句如下(按正常的顺序):

SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);

SQLDisconnect(V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

第六:关于上述情况中的错误信息处理
我们需要定义两个变量:

long     V_OD_erg;

SQLINTEGER       V_OD_err;

SQLAllocHandle、SQLSetEnvAttr、SQLSetConnectAttr、SQLConnect、SQLExecDirect、SQLNumResultCols和SQLRowCount的调用结果都可以用V_OD_erg来存储,V_OD_err可以获得SQLBindCol中的错误信息。

第七:获得本机的DSN信息
我们可以在声明SQLHENV句柄之后,使用SQLDataSources函数来获得本机的DSN信息。程序如下:

void OD_ListDSN(void)

{

char       l_dsn[100],l_desc[100];

short int  l_len1,l_len2,l_next;

l_next=SQL_FETCH_FIRST;

while( SQLDataSources(V_OD_Env,l_next,l_dsn, sizeof(l_dsn),

&l_len1, l_desc, sizeof(l_desc), &l_len2) == SQL_SUCCESS)

{

printf(“Server=(%s) Beschreibung=(%s)\n”,l_dsn,l_desc);

l_next=SQL_FETCH_NEXT;

}

}

l_next变量是用来指定我们所要获得的DSN的类别:

SQL_FETCH_FIRST 设定SQLDataSources()函数找到第一个可用的数据源(可以是User DSN,也可以是Systerm DSN)
SQL_FETCH_FIRST_USER 设定SQLDataSources()函数找到第一个User DSN
SQL_FETCH_FIRST_SYSTEM 设定SQLDataSources()函数找到第一个System DSN
SQL_FETCH_NEXT 找到下一个数据源,至于数据源类型则要根据前面的定义

到这里,我们在Unix的C语言下面进行ODBC编程已经讲完,上述ODBC API需要引用以下几个头文件(这些文件已经安装到/usr/include下了):

#include <sql.h>

#include <sqlext.h>

#include <sqltypes.h>

另外如果大家使用GTK进行编程,由于到目前为止GTK还没有加入专门处理数据库的部件,所以大家可以在GTK中调用上述的ODBC API即可。

这里附上例程供大家参考学习:

/* odbc.c

testing unixODBC

*/

#include <stdlib.h>

#include <stdio.h>

#include <odbc/sql.h>

#include <odbc/sqlext.h>

#include <odbc/sqltypes.h>

SQLHENV       V_OD_Env;    // Handle ODBC environment

long       V_OD_erg;    // result of functions

SQLHDBC       V_OD_hdbc;                      // Handle connection

char       V_OD_stat[10];    // Status SQL

SQLINTEGER     V_OD_err,V_OD_rowanz,V_OD_id;

SQLSMALLINT     V_OD_mlen,V_OD_colanz;

char             V_OD_msg[200],V_OD_buffer[200];

int main(int argc,char *argv[])

{

// 1. allocate Environment handle and register version

V_OD_erg=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Error AllocHandle\n”);

exit(0);

}

V_OD_erg=SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Error SetEnv\n”);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

// 2. allocate connection handle, set timeout

V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Error AllocHDB %d\n”,V_OD_erg);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

SQLSetConnectAttr(V_OD_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);

// 3. Connect to the datasource “web”

V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) “Test”, SQL_NTS,

(SQLCHAR*) “root”, SQL_NTS,

(SQLCHAR*) “”, SQL_NTS);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Error SQLConnect %d\n”,V_OD_erg);

SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1,

V_OD_stat, &V_OD_err,V_OD_msg,100,&V_OD_mlen);

printf(“%s (%d)\n”,V_OD_msg,V_OD_err);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

printf(“Connected !\n”);

V_OD_erg=SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Fehler im AllocStatement %d\n”,V_OD_erg);

SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat,&V_OD_err,V_OD_msg,100,&V_OD_mlen);

printf(“%s (%d)\n”,V_OD_msg,V_OD_err);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

SQLBindCol(V_OD_hstmt,1,SQL_C_CHAR, &V_OD_buffer,150,&V_OD_err);

SQLBindCol(V_OD_hstmt,2,SQL_C_ULONG,&V_OD_id,150,&V_OD_err);

V_OD_erg=SQLExecDirect(V_OD_hstmt,”SELECT dtname,iduser FROM web order by iduser”,SQL_NTS);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Error in Select %d\n”,V_OD_erg);

SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat,&V_OD_err,V_OD_msg,100,&V_OD_mlen);

printf(“%s (%d)\n”,V_OD_msg,V_OD_err);

SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);

SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

V_OD_erg=SQLNumResultCols(V_OD_hstmt,&V_OD_colanz);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);

SQLDisconnect(V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

printf(“Number of Columns %d\n”,V_OD_colanz);

V_OD_erg=SQLRowCount(V_OD_hstmt,&V_OD_rowanz);

if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))

{

printf(“Number of RowCount %d\n”,V_OD_erg);

SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);

SQLDisconnect(V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

exit(0);

}

printf(“Number of Rows %d\n”,V_OD_rowanz);

V_OD_erg=SQLFetch(V_OD_hstmt);

while(V_OD_erg != SQL_NO_DATA)

{

printf(“Result: %d %s\n”,V_OD_id,V_OD_buffer);

V_OD_erg=SQLFetch(V_OD_hstmt);

}  ;

SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt);

SQLDisconnect(V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc);

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

return(0);

}

2QT下进行ODBC编程
QT 3.0提供了Data Table、Data Browser和Data View三个与数据库相关的控件。你可以在QT的Project设置你要连接的数据库,Driver一栏中选择QODBC3即可,其它选项你一看就明白了。上述的三个数据库控件的使用方法可以参见QT中相应文档,也很好使用的。

参考资料

  1. 微软的ODBC主页: http://www.microsoft.com/data/odbc/
  2. UnixODBC的主页: http://www.unixodbc.org
  3. FreeODBC的主页: http://www.jepstone.net/FreeODBC/
  4. EasySoft的主页: http://www.easysoft.com
  5. TrollTech的QT 3.0文档主页: http://doc.trolltech.com/3.0/

2011-03-08
发表者 Venus
暂无评论

Iptables 入门配置

iptables -F (flush 清除所有的已定规则)

iptables -X (delete 删除所有用户“自定义”的链(tables))

iptables -Z (zero 将所有的chain的计数与流量统计都归零)

(1)查看本机关于IPTABLES的设置情况

[root@tp ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination        

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination        
ACCEPT     all  —  0.0.0.0/0            0.0.0.0/0          
ACCEPT     icmp —  0.0.0.0/0            0.0.0.0/0           icmp type 255
ACCEPT     esp  —  0.0.0.0/0            0.0.0.0/0          
ACCEPT     ah   —  0.0.0.0/0            0.0.0.0/0          
ACCEPT     udp  —  0.0.0.0/0            224.0.0.251         udp dpt:5353
ACCEPT     udp  —  0.0.0.0/0            0.0.0.0/0           udp dpt:631
ACCEPT     all  —  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:25
REJECT     all  —  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
可以看出我在安装linux时,选择了有防火墙,并且开放了22,80,25端口.

如果你在安装linux时没有选择启动防火墙,是这样的

[root@tp ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

什么规则都没有.

(2)清除原有规则.

不管你在安装linux时是否启动了防火墙,如果你想配置属于自己的防火墙,那就清除现在filter的所有规则.

[root@tp ~]# iptables -F      清除预设表filter中的所有规则链的规则
[root@tp ~]# iptables -X      清除预设表filter中使用者自定链中的规则

我们在来看一下

[root@tp ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination     

什么都没有了吧,和我们在安装linux时没有启动防火墙是一样的.(提前说一句,这些配置就像用命令配置IP一样,重起就会失去作用),怎么保存.

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样就可以写到/etc/sysconfig/iptables文件里了.写入后记得把防火墙重起一下,才能起作用.

[root@tp ~]# service iptables restart

现在IPTABLES配置表里什么配置都没有了,那我们开始我们的配置吧

(3)设定预设规则

[root@tp ~]# iptables -P INPUT DROP

[root@tp ~]# iptables -P OUTPUT ACCEPT

[root@tp ~]# iptables -P FORWARD DROP
上面的意思是,当超出了IPTABLES里filter表里的两个链规则(INPUT,FORWARD)时,不在这两个规则里的数据包怎么处理呢,那就是DROP(丢弃).应该说这样配置是很安全的.我们要控制流入数据包

而对于OUTPUT链,也就是流出的包我们不用做太多限制,而是采取ACCEPT,也就是说,不在这个规则里的包怎么办呢,那就是通过.

可以看出INPUT,FORWARD两个链采用的是允许什么包通过,而OUTPUT链采用的是不允许什么包通过.

这样设置还是挺合理的,当然你也可以三个链都DROP,但这样做我认为是没有必要的,而且要写的规则就会增加.但如果你只想要有限的几个规则是,如只做WEB服务器.还是推荐三个链都是DROP.

注:如果你是远程SSH登陆的话,当你输入第一个命令回车的时候就应该掉了.因为你没有设置任何规则.

怎么办,去本机操作呗!

(4)添加规则.

首先添加INPUT链,INPUT链的默认规则是DROP,所以我们就写需要ACCETP(通过)的链

为了能采用远程SSH登陆,我们要开启22端口.

[root@tp ~]# iptables -A INPUT -p tcp –dport 22 -j ACCEPT

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT (注:这个规则,如果你把OUTPUT 设置成DROP的就要写上这一部,好多人都是望了写这一部规则导致,始终无法SSH.在远程一下,是不是好了.

其他的端口也一样,如果开启了web服务器,OUTPUT设置成DROP的话,同样也要添加一条链:

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 80 -j ACCEPT ,其他同理.)

如果做了WEB服务器,开启80端口.

[root@tp ~]# iptables -A INPUT -p tcp –dport 80 -j ACCEPT
如果做了邮件服务器,开启25,110端口.

[root@tp ~]# iptables -A INPUT -p tcp –dport 110 -j ACCEPT
[root@tp ~]# iptables -A INPUT -p tcp –dport 25 -j ACCEPT
如果做了FTP服务器,开启21端口

[root@tp ~]# iptables -A INPUT -p tcp –dport 21 -j ACCEPT

[root@tp ~]# iptables -A INPUT -p tcp –dport 20 -j ACCEPT

如果做了DNS服务器,开启53端口

[root@tp ~]# iptables -A INPUT -p tcp –dport 53 -j ACCEPT

如果你还做了其他的服务器,需要开启哪个端口,照写就行了.

上面主要写的都是INPUT链,凡是不在上面的规则里的,都DROP

允许icmp包通过,也就是允许ping,

[root@tp ~]# iptables -A OUTPUT -p icmp -j ACCEPT (OUTPUT设置成DROP的话)

[root@tp ~]# iptables -A INPUT -p icmp -j ACCEPT  (INPUT设置成DROP的话)

允许loopback!(不然会导致DNS无法正常关闭等问题)

IPTABLES -A INPUT -i lo -p all -j ACCEPT (如果是INPUT DROP)
IPTABLES -A OUTPUT -o lo -p all -j ACCEPT(如果是OUTPUT DROP)

下面写OUTPUT链,OUTPUT链默认规则是ACCEPT,所以我们就写需要DROP(放弃)的链.

减少不安全的端口连接

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 31337 -j DROP

[root@tp ~]# iptables -A OUTPUT -p tcp –dport 31337 -j DROP

有些些特洛伊木马会扫描端口31337到31340(即黑客语言中的 elite 端口)上的服务。既然合法服务都不使用这些非标准端口来通信,阻塞这些端口能够有效地减少你的网络上可能被感染的机器和它们的远程主服务器进行独立通信的机会

还有其他端口也一样,像:31335、27444、27665、20034 NetBus、9704、137-139(smb),2049(NFS)端口也应被禁止,我在这写的也不全,有兴趣的朋友应该去查一下相关资料.

当然出入更安全的考虑你也可以包OUTPUT链设置成DROP,那你添加的规则就多一些,就像上边添加

允许SSH登陆一样.照着写就行了.

下面写一下更加细致的规则,就是限制到某台机器

如:我们只允许192.168.0.3的机器进行SSH连接

[root@tp ~]# iptables -A INPUT -s 192.168.0.3 -p tcp –dport 22 -j ACCEPT

如果要允许,或限制一段IP地址可用 192.168.0.0/24 表示192.168.0.1-255端的所有IP.

24表示子网掩码数.但要记得把 /etc/sysconfig/iptables 里的这一行删了.

-A INPUT -p tcp -m tcp –dport 22 -j ACCEPT 因为它表示所有地址都可以登陆.

或采用命令方式:

[root@tp ~]# iptables -D INPUT -p tcp –dport 22 -j ACCEPT

然后保存,我再说一边,反是采用命令的方式,只在当时生效,如果想要重起后也起作用,那就要保存.写入到/etc/sysconfig/iptables文件里.

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样写 !192.168.0.3 表示除了192.168.0.3的ip地址

其他的规则连接也一样这么设置.

在下面就是FORWARD链,FORWARD链的默认规则是DROP,所以我们就写需要ACCETP(通过)的链,对正在转发链的监控.

开启转发功能,(在做NAT时,FORWARD默认规则是DROP时,必须做)

[root@tp ~]# iptables -A FORWARD -i eth0 -o eth1 -m state –state RELATED,ESTABLISHED -j ACCEPT

[root@tp ~]# iptables -A FORWARD -i eth1 -o eh0 -j ACCEPT

丢弃坏的TCP包

[root@tp ~]#iptables -A FORWARD -p TCP ! –syn -m state –state NEW -j DROP

处理IP碎片数量,防止攻击,允许每秒100个

[root@tp ~]#iptables -A FORWARD -f -m limit –limit 100/s –limit-burst 100 -j ACCEPT

设置ICMP包过滤,允许每秒1个包,限制触发条件是10个包.

[root@tp ~]#iptables -A FORWARD -p icmp -m limit –limit 1/s –limit-burst 10 -j ACCEPT

我在前面只所以允许ICMP包通过,就是因为我在这里有限制.

二,配置一个NAT表放火墙

1,查看本机关于NAT的设置情况

[root@tp rc.d]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination        

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination        
SNAT       all  —  192.168.0.0/24       anywhere            to:211.101.46.235

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

我的NAT已经配置好了的(只是提供最简单的代理上网功能,还没有添加防火墙规则).关于怎么配置NAT,参考我的另一篇文章

当然你如果还没有配置NAT的话,你也不用清除规则,因为NAT在默认情况下是什么都没有的

如果你想清除,命令是

[root@tp ~]# iptables -F -t nat

[root@tp ~]# iptables -X -t nat

[root@tp ~]# iptables -Z -t nat

2,添加规则

添加基本的NAT地址转换,(关于如何配置NAT可以看我的另一篇文章),

添加规则,我们只添加DROP链.因为默认链全是ACCEPT.

防止外网用内网IP欺骗

[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 10.0.0.0/8 -j DROP
[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 172.16.0.0/12 -j DROP
[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 192.168.0.0/16 -j DROP
 如果我们想,比如阻止MSN,QQ,BT等的话,需要找到它们所用的端口或者IP,(个人认为没有太大必要)

例:

禁止与211.101.46.253的所有连接

 [root@tp ~]# iptables -t nat -A PREROUTING  -d 211.101.46.253 -j DROP

禁用FTP(21)端口 

[root@tp ~]# iptables -t nat -A PREROUTING -p tcp –dport 21 -j DROP

这样写范围太大了,我们可以更精确的定义.

[root@tp ~]# iptables -t nat -A PREROUTING  -p tcp –dport 21 -d 211.101.46.253 -j DROP

这样只禁用211.101.46.253地址的FTP连接,其他连接还可以.如web(80端口)连接.

按照我写的,你只要找到QQ,MSN等其他软件的IP地址,和端口,以及基于什么协议,只要照着写就行了.

最后:

drop非法连接
[root@tp ~]# iptables -A INPUT   -m state –state INVALID -j DROP
[root@tp ~]# iptables -A OUTPUT  -m state –state INVALID -j DROP
[root@tp ~]# iptables-A FORWARD -m state –state INVALID -j DROP
允许所有已经建立的和相关的连接
[root@tp ~]# iptables-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
[root@tp ~]# iptables-A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样就可以写到/etc/sysconfig/iptables文件里了.写入后记得把防火墙重起一下,才能起作用.

[root@tp ~]# service iptables restart

别忘了保存,不行就写一部保存一次.你可以一边保存,一边做实验,看看是否达到你的要求

2011-03-08
发表者 Venus
暂无评论

NFS服务配置文件

NFS服务的安装和测试是比较简单的。那么下面我们就来详细介绍一下NFS服务在Linux系统下的具体安装测试步骤。那么请大家先了解一下有关的配置文件,以及相关的格式。

1)服务端配置文件: /etc/exports

文件格式: Directory hostname (options)

Directory 为要共享的目录;

hostname 客户机的域名/IP地址/IP地址段;也可以为空,空则代表任意主机;

options 可选,如不指定,则采用默认选项.如ro,rw,sync,async等;

如:

以下是代码片段:

/home 192.168.1.* (rw,async,no_root_squash)

Rw;可读可写

Async;同步,服务端只有接受到客户端的回应,才进行下一步,以确保连接更可靠

sync:数据同步写入内存和硬盘,也可以使用async,此时数据会先暂存于内存中,而不立即写入硬盘。

No_root_squash;NFS 服务器共享目录用户的属性,如果用户是 root,那么对于这个共享目录来说就具有 root 的权限。不压缩root用户的权限,如要更安全请用roo_squash

在服务端可以用exportfs命令来输出exports对外共享的目录;

2)确保启动portmap和NFS

以下是代码片段:

# /etc/rc.d/init.d/portmap start (or: # /service portmap start )

# /etc/rc.d/init.d/nfs start (or: # /serverice nfs start)

注:可用netstat &ndash;untlp,来查看portmap和nfs服务是否启动,2049端口就是NFS服务器,111端口对应的就是portmap服务,可以发现在TCP和UDP上都有对应的端口;

3) NFS客户端配置(mount或fstab文件)

以下是代码片段:

# mount &ndash;t nfs hostname(orIP):/directory /mountpoint

-t nfs可以省略;

/directory为绝对路径;

或是在/etc/fstab文件中增加NFS文件系统的挂载记录

以下是代码片段:

NFSserverIP:/directory /mountpoint nfs defaults 0 0

可以用mount查一下挂载点的情况.

2011-03-07
发表者 Venus
暂无评论

SELinux is preventing the http daemon from connecting to network port 3306 For complete SELinux messages

Mar  7 10:04:59 s1 setroubleshoot: SELinux is preventing the http daemon from connecting to network port 3306 For complete SELinux messages. run sealert -l 8317c5f8-15b1-48cb-854f-294d207f83b2

[root@s1 ~]# sealert -l 8317c5f8-15b1-48cb-854f-294d207f83b2

摘要:

SELinux is preventing the http daemon from connecting to network port 3306

详细的描述:

[SELinux is in permissive mode, the operation would have been denied but was
permitted due to permissive mode.]

SELinux has denied the http daemon from connecting to 3306. An httpd script is
trying to do a network connect to a remote port. If you did not setup httpd to
network connections, this could signal a intrusion attempt.

正在允许访问:

If you want httpd to connect to network ports you need to turn on the
httpd_can_network_network_connect boolean: “setsebool -P
httpd_can_network_connect=1″

以下命令将允许这个权限:

setsebool -P httpd_can_network_connect=1

附加的信息:

源上下文                  root:system_r:httpd_t
目标上下文               system_u:object_r:mysqld_port_t
目标对象                  None [ tcp_socket ]
Source                        httpd
Source Path                   /usr/sbin/httpd
Port                          3306
Host                          s1
Source RPM Packages           httpd-2.2.3-43.el5
Target RPM Packages
策略 RPM                    selinux-policy-2.4.6-279.el5
Selinux 激活                True
策略类型                  targeted
MLS 激活                    True
强制模式                  Permissive
插件名称                  httpd_can_network_connect
主机名                     s1
平台                        Linux s1 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39
                              EDT 2010 x86_64 x86_64
警告记数                  960
First Seen                    Mon Mar  7 09:04:13 2011
Last Seen                     Mon Mar  7 10:08:16 2011
Local ID                      8317c5f8-15b1-48cb-854f-294d207f83b2
行数

原始 Audit 消息

host=s1 type=AVC msg=audit(1299463696.250:1396): avc:  denied  { name_connect }                  for  pid=14554 comm=”httpd” dest=3306 scontext=root:system_r:httpd_t:s0 tcontext                 =system_u:object_r:mysqld_port_t:s0 tclass=tcp_socket

host=s1 type=SYSCALL msg=audit(1299463696.250:1396): arch=c000003e syscall=42 su                 ccess=no exit=-115 a0=f a1=7fff7d8e7d60 a2=10 a3=0 items=0 ppid=14550 pid=14554                  auid=0 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none                 ) ses=55 comm=”httpd” exe=”/usr/sbin/httpd” subj=root:system_r:httpd_t:s0 key=(n                 ull)

[root@s1 ~]#
[root@s1 ~]# setsebool -P

Usage:  setsebool [ -P ] boolean value | bool1=val1 bool2=val2…

[root@s1 ~]# httpd_can_network_connect=1
[root@s1 ~]# setenforce 1

2011-02-28
发表者 Venus
暂无评论

kernel-PAE Linux32位支持4G以上内存

      今天安装新服务器,(redhat5.5 、16GB内存)遇到内核变为kernel-pae,找了相关资料后:kernel-PAE,用于拥有超过 4GB RAM 的 32-bit x86 系统中,或 CPU 带有 “NX (No eXecute)” 特性的系统中。他同时支持单/多处理器系统。

PAE:Physical Address Extension,PAE 是 Intel 提供的内存地址扩展机制,他通过在宿主操作系统中使用 Address Windowing Extensions API 为应用程式提供支持,从而让处理器将能够用来寻址物理内存的位数从 32 位扩展为 36 位。

32位linux系统,最大只能识别到4GB内存,在需要支持更大的话,就需要kernel-pae这个内核了。