- 论坛徽章:
- 0
|
看到不少关于如何控制网络登陆的好帖子
这里贴个自己写的在本人所在单位使用的东东
还请高人指正
- /* mytcpwrap.c
- 功能:类似著名的 tcpwrap
- 根据配置文件,允许某些地址的用户进行登陆连接
- 除可记录登陆时间外,还可以记录退出时间
- 本程序应由超级服务器inetd启动
- 使用:替换/etc/inetd.conf 中要进行控制的端口
- 以telnet、ftp端口控制为例:
- /etc/inetd.conf 原内容:
- ftp stream tcp nowait root /etc/ftpd ftpd
- telnet stream tcp nowait NOLUID /etc/telnetd telnetd
- 改为:
- ftp stream tcp nowait root /etc/mytcpwrap /etc/ftpd
- telnet stream tcp nowait NOLUID /etc/mytcpwrap /etc/telnetd
- 注意:改完后记得通知一下inetd进程
- */
- #include "stdio.h"
- #include "errno.h"
- #include "time.h"
- #include "signal.h"
- #include <sys/types.h>;
- #include <sys/socket.h>;
- #include <netinet/in.h>;
- #include <netdb.h>;
- #include "sys/stat.h"
- #include "sys/times.h"
- #define INET_ADDRESTRLEN 18
- #define MAXSOCKADDR 64
- /* 地址配置文件
- 格式 port ips
- '#' 打头表示本行为注释
- 'S' 打头表示网络日志记录地,格式为 S port ips
- 缺省为 5678 1.1.1.1
- 接受通配符 *
- 其中 port 记录本地端口,可以使用通配符 * 表示任意端口
- ips 允许访问的远程IP地址,形如 nnn.nnn.nnn.nnn
- 可以使用通配符 * 表示任意地址
- 例: 21 1.1.1.1 表示1.1.1.1的机器可以访问本机21(ftp)端口
- * 2.2.2.2 表示2.2.2.2的机器可以访问本机任意端口
- 23 3.3.3.* 表示3.3.3.*网段的机器可以访问本机23(telnet)端口
- */
- #define INIFILE "/etc/mytcpwrap.conf"
- #define LOGFILE "/usr/adm/mytcpwrap.log"
- short R_PORT=5678;
- char R_ADDR[16]="1.1.1.1";
- /* 简单字符串比较函数 */
- int cj_Compare(char *so, char *sd)
- {
- char *to,*td;
- int done,cjOk=0,i,k;
- if (*sd==0) return 0;
- for (done=0,to=so,td=sd;!done; ) {
- if (*td=='?') {
- td++; to++;
- }
- else if (*td=='*') {
- if (cj_Compare(to,(td+1))==0) return 0;
- else to++;
- }
- else {
- cjOk = done = *to - *td;
- td++; to++;
- }
- if (*to==0) for ( ;(*td=='?')||(*td=='*');td++);
- if ((*to==0)&&(*td==0)) break;
- else if (*to==0) done = cjOk = -1;
- else if (*td==0) done = cjOk = -1;
- }
- return cjOk;
- }
- int is_denied(char *s, int lport)
- {
- int k, ct;
- char buf[128], ips[32], pts[8];
- FILE *fp;
- /* 读配置文件 */
- fp = fopen(INIFILE, "rt");
- if (fp){
- memset(buf, 0, sizeof(buf));
- fgets(buf, sizeof(buf)-1, fp);
- while (!feof(fp)){
- memset(pts, 0, sizeof(pts));
- memset(ips, 0, sizeof(ips));
- sscanf(buf, "%5s%15s", pts, ips);
- if (pts[0]!='#'){
- if (pts[0]!='S' && pts[0]!='s'){
- /* 去除末尾单独的'.' */
- while (ips[strlen(ips)-1]=='.') ips[strlen(ips)-1]=0;
- for (ct=k=0;k<strlen(ips);k++)
- if (ips[k]=='.') ct++;
- /* 补齐 nnn.nnn.nnn.nnn 的格式 */
- while (ct<3){
- strcat(ips, ".*"); ct++;
- }
- /* 端口号是否一致或是任意端口 */
- if (pts[0]=='*' || atoi(pts)==lport){
- /* 比较IP地址是否满足匹配规则 */
- if (cj_Compare(s, ips)==0){
- fclose(fp);
- /* 返回成功--接受登录 */
- return 0;
- }
- }
- }
- else{
- /* 读网络日志服务器地址、端口 */
- memset(pts, 0, sizeof(pts));
- memset(ips, 0, sizeof(ips));
- sscanf(buf, "%*s%5s%15s", pts, R_ADDR);
- R_PORT = atoi(pts);
- }
- }
- memset(buf, 0, sizeof(buf));
- fgets(buf, sizeof(buf)-1, fp);
- }
- fclose(fp);
- }
- /* 未找到匹配记录,拒绝登录 */
- return 1;
- }
- char *inet_ntop(int f, void *a, char *s, int l)
- {
- u_char *p=(u_char *)a;
- struct in_addr inv;
- char tt[INET_ADDRESTRLEN];
- if (f==AF_INET){
- snprintf(tt, sizeof(tt), "%d.%d.%d.%d",p[0], p[1], p[2], p[3]);
- if (strlen(tt)>;l){
- errno = ENOSPC;
- return NULL;
- }
- strcpy(s, tt);
- return tt;
- }
- errno = EAFNOSUPPORT;
- return NULL;
- }
- sock_ntop(struct sockaddr * sa, int len, char *s)
- {
- char str[128];
- int pt=-1;
- struct sockaddr_in *sin=(struct sockaddr_in *)sa;
- s[0] = 0;
- switch(sa->;sa_family){
- case AF_INET:if (inet_ntop(AF_INET, &sin->;sin_addr, str, sizeof(str))==NULL)
- return NULL;
- pt = ntohs(sin->;sin_port);
- strcpy(s, str);
- break;
- };
- return pt;
- }
- get_time(int t[6])
- {
- struct tm *tm;
- time_t n;
- n = time(NULL);
- tm = localtime(&n);
- t[0] = tm->;tm_year + 1900;
- t[1] = tm->;tm_mon+1;
- t[2] = tm->;tm_mday;
- t[3] = tm->;tm_hour;
- t[4] = tm->;tm_min;
- t[5] = tm->;tm_sec;
- }
- long rowid=0;
- /* 将登录信息记录到网络上日志服务器上
- 通过两次提交记录完整的登陆、退出时间
-
- 第一次记录登录时间
- 发送格式: NETLOG|本地服务端口|客户地址|端口|成功标志|
- 服务端返回一个该记录的rowid值
- 第二次记录离开时间
- 发送格式: NETUPD|原记录的rowid
- */
- int net_logit(int lport, char *ips, int rport, int succ)
- {
- int i,s;
- struct sockaddr_in sin;
- struct hostent *hp;
- char buf[128], ss[64];
- if (R_PORT==0 || strlen(R_ADDR)==0) return -1;
- bzero((char *)&sin,sizeof(sin));
- sin.sin_family = AF_INET;
- /* 取日志服务器地址 */
- hp = gethostbyname(R_ADDR);
- if (hp!=NULL)
- bcopy(hp->;h_addr, (char *)&sin.sin_addr, hp->;h_length);
- else
- inet_aton(R_ADDR, &sin.sin_addr);
- sin.sin_port = htons(R_PORT);
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s<0) return 1;
- /* 连接日志服务器 */
- if ((i=connect(s, (struct sockaddr *)&sin,sizeof(sin)))<0){
- close(s);
- return 2;
- }
- /* 发送日志信息 格式: NETLOG|本地服务端口|客户地址|端口|成功标志| */
- /* 第一次记录登录时间 */
- if (rowid==0)
- sprintf(ss, "NETLOG|%d|%s|%d|%d|", lport, ips, rport, succ);
- else
- /* 第二次记录离开时间,发送信息格式: NETUPD|原记录的rowid */
- sprintf(ss, "NETUPD|%d|", rowid);
- sprintf(buf, "%04d%s", strlen(ss), ss);
- write(s, buf, strlen(buf));
- memset(ss, 0, sizeof(ss));
- if (rowid==0){
- /* 取该记录的rowid */
- read(s, ss, sizeof(ss)-1);
- rowid = atol(ss);
- }
- /* 关闭连接 */
- shutdown(s, 2);
- close(s);
- return 0;
- }
- void mysig(int sig)
- {
- return ;
- }
- main(int argc, char *argv[], char *envp[])
- {
- int srq[6], i, ct, k, rport, lport;
- unsigned int len;
- char buf[128], ips[32];
- FILE *fp;
- union{
- struct sockaddr sa;
- char data[MAXSOCKADDR];
- }from;
- /* 取本地端口 */
- len = sizeof(from);
- k = getsockname(1, (struct sockaddr *)&from.data, &len);
- lport = sock_ntop(&from.sa, len, ips);
- /* 取远程端口、地址 */
- len = sizeof(from);
- k = getpeername(1, (struct sockaddr *)&from.data, &len);
- rport = sock_ntop(&from.sa, len, ips);
- get_time(srq);
- sprintf(buf, "端口 %d, 来自 %15s:%d, 时间 %04d/%02d/%02d %02d:%02d:%02d ",
- lport, ips, rport, srq[0], srq[1], srq[2],
- srq[3], srq[4], srq[5]);
- fp = fopen(LOGFILE, "at");
- if (fp!=NULL)
- fprintf(fp, "%s", buf);
- k = is_denied(ips, lport);
- /* 记录登录时间 */
- net_logit(lport, ips, rport, k);
- if (k){
- fprintf(stderr,"对不起,您没有在此主机登录的权限!\007\r\n");
- if (fp!=NULL){
- fprintf(fp, "...拒绝[%d]!\n", rowid);
- fclose(fp);
- }
- exit(1);
- }
- if (fp){
- fprintf(fp, "...接受[%s][%d]!\n", argv[0], rowid);
- fclose(fp);
- }
- sigset(SIGCLD, mysig);
- /* 子进程启动相应程序,父进程等待 */
- if (fork()==0)
- execve(argv[0], argv, envp);
- else pause();
- /* 记录退出登录的时间 */
- net_logit(lport, ips, rport, k);
- return 0;
- }
复制代码 |
|