Categories
C/C++

ip地址查询(C++版)

最近公司服务器被hack,怀疑的ip每次都登录ip138.com查询,很麻烦,想起维护新糊涂的时候,曾经写个小程序统计用户ip地址来源。ip数据库是纯真版,代码是参考别人的,忘了是谁写的,我就只修改了main函数。

/**
 * file: ip_from.cpp
 * @date: 2007.4.20
 *
 */

#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <ios>
#include <fstream>
#include <vector>
#include <iterator>
#include <stdexcept>
#include <algorithm>
using namespace std;

typedef unsigned int IP_TYPE;

const int  IP_SIZE = 4;
const int  OFFSET_SIZE = 3;
const int  INDEX_RECORD_SIZE = IP_SIZE + OFFSET_SIZE;

class IpLocater {
private:
    FILE* dbfile;
    int   first_index;
    int   last_index;
    enum  { REDIRECT_MODE_1 = 0x01, REDIRECT_MODE_2 = 0x02 };
protected:

public:
    IpLocater(const string dbfilename = "QQWry.Dat")
    {
        dbfile = fopen(dbfilename.c_str(),"rb");
        if (!dbfile) {
            printf("can not open the ip db file %s\n", dbfilename.c_str());
            exit(0);
        }

        fread(&first_index, sizeof(int), 1, dbfile);
        fread(&last_index, sizeof(int), 1, dbfile);
    }
    ~IpLocater(){
        fclose(dbfile);
    }

    int getRecordCount() const {
        return (last_index - first_index ) / INDEX_RECORD_SIZE + 1;
    }
    
    string readString(const int offset = 0){
        if (offset) {
            fseek(dbfile, offset, SEEK_SET);
        }

        char ch = fgetc(dbfile);
        ostringstream sstr ;
        while (ch != 0 && ch != EOF) {
            sstr << ch;
            ch = fgetc(dbfile);
        }
        return sstr.str();
    }

    inline int readInt3(const int offset = 0 ) {
        if (offset) {
            fseek(dbfile,offset,SEEK_SET);
        }
    
        int result = 0;
        fread(&result, sizeof(char), 3, dbfile);
        return result;
    }

    string readAreaAddr(const int offset = 0) {
        if (offset) {
            fseek(dbfile, offset, SEEK_SET);
        }
        char b = fgetc(dbfile);
        if (b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {
            int areaOffset = 0;
            fread(&areaOffset, 1, 3, dbfile);
            if (areaOffset) {
                return readString(areaOffset);
            } else {
                return "Unkown";
            }
        } else {
            fseek(dbfile, -1, SEEK_CUR);
            return readString();
        }
    }

    unsigned int readLastIp(const int offset) {
        fseek(dbfile, offset, SEEK_SET);
        unsigned int ip = 0;
        fread(&ip, sizeof(unsigned int), 1, dbfile);
        return ip;
    }

    string readFullAddr(const int offset, int ip = 0) {
        string address = "";

        fseek(dbfile, offset + 4, SEEK_SET);

        char ch = fgetc(dbfile);
        if (ch == REDIRECT_MODE_1) {
            int countryOffset = 0;
            fread(&countryOffset,sizeof(char),3,dbfile);
            
            fseek(dbfile, countryOffset, SEEK_SET);
            char byte = fgetc(dbfile);
            if (byte == REDIRECT_MODE_2 ) {
                int p = 0;
                fread(&p, 1, 3, dbfile);
                address = readString(p);
                fseek(dbfile, countryOffset + 4, SEEK_SET);
            } else {
                address = readString(countryOffset);
            }
            address += readAreaAddr(); // current position
        } else if (ch == REDIRECT_MODE_2) {
            int p = 0;
            fread(&p, 1, 3, dbfile);
            address = readString(p);
            address += readAreaAddr(offset + 8);
        } else {
            fseek(dbfile, -1, SEEK_CUR);
            address = readString();
            address += readAreaAddr();
        }

        return address;
    }

    void printAddr(int first = 0, int count = 100){
        int record_count  = getRecordCount();
        for (int i = first; i< first+count && i<record_count; i++)
        {
            fseek(dbfile,i*INDEX_RECORD_SIZE+first_index,SEEK_SET);
            unsigned int ip = 0;
            fread(&ip,sizeof(unsigned int),1,dbfile);
            int offset = 0;
            fread(&offset,1,OFFSET_SIZE,dbfile);
            cout << ip2string(ip) << "-" << ip2string(readLastIp(offset))
                << readFullAddr(offset) << endl;
        }
    }

    int find(unsigned int ip,int left ,int right) {
        if (right - left == 1) {
            return left;
        } else {
            int middle = (left + right) / 2;
            
            int offset = first_index + middle * INDEX_RECORD_SIZE;
            fseek(dbfile,offset,SEEK_SET);
            unsigned int new_ip = 0;
            fread(&new_ip,sizeof(unsigned int),1,dbfile);
            
            if (ip >= new_ip) {
                return find(ip,middle,right);
            } else {
                return find(ip,left,middle);
            }
        }
    }

    string getIpAddr( unsigned int ip){
        int index = find(ip,0, getRecordCount() - 1 );
        int index_offset = first_index + index * INDEX_RECORD_SIZE + 4;
        int addr_offset = 0;
        fseek(dbfile,index_offset,SEEK_SET);
        fread(&addr_offset,1,3,dbfile);
        string address = readFullAddr( addr_offset,ip );
        return address;
    }
    
    string ip2string( unsigned int ip) const{
        ostringstream sstr;
        sstr << ((ip & 0xff000000)>>24) ;
        sstr << "." << ((ip & 0xff0000)>>16);
        sstr << "." << ((ip & 0xff00)>>8);
        sstr << "." << (ip & 0xff);
        return sstr.str();
    }

    unsigned int string2ip(const string ipstr)const{
        string str = ipstr;
        unsigned int ip = 0;
        int p = 0;
        p = str.find(".");
        ip += atoi(str.substr(0,p).c_str());
        ip <<= 8;
        str = str.substr(p+1,str.length());
        p = str.find(".");
        ip += atoi(str.substr(0,p).c_str());
        ip <<= 8;
        str = str.substr(p+1,str.length());
        p = str.find(".");
        ip += atoi(str.substr(0,p).c_str());
        ip <<= 8;
        ip += atoi(str.substr(p+1,str.length()).c_str());
        return ip;
    }

    string getIpAddr(string ip){

        return getIpAddr( string2ip( ip ) );
    }
};

int main(int argc, char* argv[])
{
    IpLocater locater("/var/opt/QQWry.Dat");
#if 0   
    if (argc > 1) {
        string ip = argv[1];
        cout << locater.getIpAddr(ip) << endl;
    } else {
        string str;
        while (cin >> str) {
            cout << locater.getIpAddr(str) << endl;
        }
    }
#endif

    long counter = 0;

    if (argc > 1) {
        string file_name = argv[1];
        ifstream infile(file_name.c_str(), ios::in);

        if (!infile) {
            cerr << "oops: unable to open log file"
                << file_name << '\n';
            return -1;
        }

        string tmp;
        vector<string> vect;

        try {
            while (getline(infile, tmp, '\n'))
                vect.push_back(tmp.substr(0, tmp.find(' ')));
        } catch (exception& e) {
            cout << e.what() << '\n';
        }

        sort(vect.begin(), vect.end());
        vector<string>::iterator it = unique(vect.begin(), vect.end());
        typedef vector<string>::const_iterator iter;
        streamsize prec = cout.precision();

        for (iter i = vect.begin(); i != it; ++i) {
            ++counter;
            cout << setprecision(18) << *i << '\t';
            cout << setprecision(prec) << locater.getIpAddr(*i) << endl;
        }
    } else {
        string str;
        while (cin >> str) {
            cout << locater.getIpAddr(str) << endl;
        }
    }

    cout << "Today the web access ip total is: " << counter << endl;

    return 0;
}

编译:
g++ -Wall -o ip_from ip_from.cpp

代码写死了,记得ip纯真数据库放在 /var/opt/QQWry.Dat 主要用来分析apache的日志。

newytht:~/bin$ cat stat_ip_from

#!/bin/sh

now=`date +"%Y%m%d"`
log_file="/usr/local/apache2/logs/access_log.$now"

if [ -f $log_file ]; then
	ipnum=`./ip_from '  < /usr/local/apache2/logs/access_log.$now ;
	echo "$ipnum"  >> /home/bbs/0Announce/bbslist/ip_stat_from
fi
If you enjoyed this post, make sure you subscribe to my RSS feed!

Leave a Reply

Your email address will not be published. Required fields are marked *