LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 785|回复: 0

Linux下半开端口扫描程序只能扫描本机 不能扫外部的IP

[复制链接]
发表于 2009-6-8 23:13:29 | 显示全部楼层 |阅读模式
这是个基于B/S的端口扫描程序,服务端为linux,但以下代码却只能扫描服务器本身  扫服务器时  能正确扫描  也能返回到浏览器   扫外面的IP则没有反应    不知道是怎么回事   请大家帮忙分析分析吧    先谢谢大家了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

/* use a bigger value if you have a slow machine or slow connection and
* you notive packet-loss. Value is interpreted as microseconds, and if
* it's set to zero it will just give up the process' timeslice.
*/
#define USLEEP_MS        0

int usage(char *p)
{
        fprintf(stderr, "usage: %s <src-ip> <dst-ip> [portrange]\n\n", p);
        fprintf(stderr, "dst-ip\t\tcan be ip-address or hostname\n");
        fprintf(stderr, "portrange\tstart-end, e.g. 1024-1500\n");
        return 1;
}

/* this function parses a statement like "1024-1500" into a high value
* and a low value. If the users messes this up on commandline, he's
* got a problem, because this function won't switch them :-)
*/
void parse_portrange(unsigned short *lo, unsigned short *hi, char *s)
{
        char *p;

        p = s;
        while(*s && *s != '-')
                s++;
        *(s++) = '\0';

        *lo = atoi(p);
        *hi = atoi(s);
}

/* this function calculates the checksum for the IP and TCP header */
u_short in_cksum(u_short *addr, int len)
{
        u_short i = 0, *word = addr;
        u_long acc = 0;
       
        while(i++ < len / 2)
                acc += *(word++);
       
        return ~(*(u_short*)&acc + *((u_short*)&acc + 1));
}

/* this function calculates the TCP-checksum with its pseudo-header as
* described in RFC 793.
*/
u_short tcp_cksum(struct iphdr *ip, struct tcphdr *tcp)
{
        char header[32], *p = header;

        /* the pseudo-header includes the source-address, the destination-
         * address (each 32 bit), 8 bit set to zero, 8 bit with the protocol
         * and 16 bit with the TCP-packet's length. The rest of the header
         * is the 'real' TCP-header.
         */
        *(unsigned long*)p = ip->saddr;
        p += 4;
        *(unsigned long*)p = ip->daddr;
        p += 4;
        *p = 0;
        p++;
        *p = ip->protocol;
        p++;
        *(unsigned short*)p = htons(4 * tcp->doff);
        p += 2;
        memcpy(p, tcp, 4 * tcp->doff);

        return in_cksum((unsigned short*)header, 32);
}

/* this function sends the SYN-packets out to the net */
int do_scan(int s, unsigned long src, unsigned long dst,
        unsigned short lo, unsigned short hi)
{
        struct iphdr *ip;
        struct tcphdr *tcp;
        char packet[sizeof(*ip) + sizeof(*tcp)];
        struct sockaddr_in to;
        unsigned short i;

        ip = (struct iphdr*) packet;
        tcp = (struct tcphdr*) (packet + sizeof(*ip));

        memset(packet, 0, sizeof(packet));

        ip->ihl = 5;
        ip->version = 4;        /* still IPv4 */
        ip->tot_len = htons(sizeof(packet));
        ip->ttl = 64;
        ip->protocol = IPPROTO_TCP;
        ip->saddr = src;
        ip->daddr = dst;
        ip->check = in_cksum((unsigned short*)ip, sizeof(*ip));

        to.sin_addr.s_addr = dst;
        to.sin_family = AF_INET;
        to.sin_port = 0;        /* irrelevant */

        tcp->doff = 5;
        tcp->source = htons(1024);
        tcp->seq = rand();
        tcp->syn = 1;
        tcp->window = htons(1024);

        for(i = lo; i <= hi; i++)
        {
                usleep(USLEEP_MS);
                tcp->dest = htons(i);
                tcp->check = 0;

                tcp->check = tcp_cksum(ip, tcp);
               
                if (sendto(s, packet, sizeof(packet), 0,
                        (struct sockaddr*)&to, sizeof(to)) == -1)
                {
                        perror("sendto() failed");
                        return 1;
                }
        }

        close(s);

        return 0;
}

/* this function is called when a packed is received. First it checks whether
* it's a packet for our purposes or not, then it examines it further.
*/
int got_packet(char *packet, int len, unsigned long target,
                unsigned short lo, unsigned short hi)
{
        struct iphdr *ip;
        struct tcphdr *tcp;
        struct servent *srv;
        char *name;
        double prcnt;
        unsigned short port;
        int ret = 0;

        ip = (struct iphdr*) packet;
        tcp = (struct tcphdr*) (packet + sizeof(*ip));

        /* our packet? */
        if (ip->saddr != target)
                return 0;

        port = htons(tcp->source);

        /* a bit statistic information for the inpatient user */
        prcnt = (port -lo) /((hi - lo) / 100.0);
        //printf("%i (%.1f%%)\r", port, prcnt);
        fflush(stdout);
       
        /* finished? */
        if (port == hi)
                ret = 1;
       
        /* not a SYN|ACK? */
        if (!(tcp->syn && tcp->ack))
                return ret;
       
        /* what service is it? */
        if ( (srv = getservbyport(tcp->source, "tcp")) == NULL)
                name = "unknown";
        else
                name = srv->s_name;

        /* and tell the user about it */
        printf("%i (%s)         \n", port, name);

        return ret;
}

/* the main-function that does all the rest */
int main(int argc, char *argv[])
{
        int s, on, pid, bytes;
        unsigned short lo, hi;
        unsigned long target;
        struct hostent *host;
        char buffer[4096];

        if (argc < 3)
                return usage(argv[0]);

        /* create the socket */
        if ( (s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
        {
                perror("socket() failed");
                return 2;
        }

        /* set the IP_HDRINCL option */
        on = 1;
        if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
        {
                perror("setsockopt() for IP_HDRINCL failed");
                return 3;
        }

        /* user-defined ports or builtin range? */
        if (argc > 3)
                parse_portrange(&lo, &hi, argv[3]);
        else
        {
                lo = 1;
                hi = 1024;
        }

        /* resolve hostname if needed */
        if ((target = inet_addr(argv[2])) == -1)
        {
                host = gethostbyname(argv[2]);
                if (!host)
                {
                        herror("gethostbyname() failed");
                        return 4;
                }
                target = ((struct in_addr*)host->h_addr)->s_addr;
        }

        printf("SYN-scanning %s (%s), ports %i - %i\n", argv[2],
                inet_ntoa(*(struct in_addr*)&target), lo, hi);

        if ( (pid = fork()) == -1)
        {
                perror("fork() failed");
                return 5;
        }

        /* the child sends the packets */
        if (pid == 0)
                exit(do_scan(s, inet_addr(argv[1]), target, lo, hi));

        /* the parent receives them and prints out the results */
        while( (bytes = read(s, buffer, sizeof(buffer)) > 0))
                if (got_packet(buffer, bytes, target, lo, hi))
                        break;

        close(s);

        return 0;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表