|
- //////////////////////////////////////////////////////////////////////
- // IP traffic analyzer
- // Written by Jonathan A. Foster <ChipMaster@YeOlPiShack.net>
- // Started April 23rd, 2021
- //
- // The idea is to analyze iptables LOG entries in combination with
- // DNSmasq's query log entries and combine them to list the hosts
- // that were accessed. The main reasons for not just inspecting HTTP
- // packets through a netfilter socket is due to HTTPS hiding the
- // "host" field. So I'm deducing based on DNS query timing.
- //
- // NOTE: its assumed that the log being processed is in chronological
- // order. This is the usual way things get logged. ;-)
- //
- // 2021-05-14 <ChipMaster@YeOlPiShack.net>
- // Dumbed down for < C++11.
- // Split into modules
- //
- // 2021-06-18 <ChipMaster@YeOlPiShack.net>
- // Wrapped in application object and added command line handling.
- // This includes:
- // - Getting config file name from CLI args
- // - Getting input and output filenams from CLI args
- // - Reading and writing from STDIN & STDOUT
- // - Send all non-data output to stderr
- //
- // 2021-08-11 <ChipMaster@YeOlPiShack.net>
- // Move main data colation routine into its own class to be shared
- // with multiple tools.
- //////////////////////////////////////////////////////////////////////
-
- #include <string.h>
- #include <string>
- #include <iostream>
- #include <fstream>
- #include <stdexcept>
- #include <vector>
- #include <map>
- #include "cli.h"
- #include "strutil.h"
- #include "data.h"
- #include "config.h"
- using namespace std;
-
-
-
- //////////////////////////////////////////////////////////////////////
- // Application class to process files.
- //////////////////////////////////////////////////////////////////////
- //#define DEBUG
-
- struct IPtraffic: public cBaseApp {
- Config config;
- LogAnalyzer analyze;
- istream *log;
- ostream *out;
- LiveBug bug;
- int line_no;
-
-
-
- IPtraffic(): out(&cout), log(0)
- { // I'd rather this initialization be static...
- analyze.us = &(config.us.vals);
- }
-
-
-
- ~IPtraffic() { if(log && log!=&cin) delete(log); }
-
-
-
- void dlog(const string msg) {
- #ifdef DEBUG
- cerr << line_no << ": " << msg << endl;
- #endif
- }
-
-
- // TODO: elaborate
- int help() {
- cerr <<
- "\n"
- "iptraffic -c {config file} [-o {output file}] [{input file} [...]]\n";
- return ExitCode = 1;
- }
-
-
-
- unsigned do_switch(const char *sw) {
- if((sw[0]=='c' || sw[0]=='o') && sw[1]==0) return 1;
- throw CLIerror("Unrecognized Switch");
- }
-
-
-
- void do_switch_arg(const char *sw, const std::string &val) {
- switch(*sw) {
- case 'c':
- config.load(val);
- if(!config.us.vals.size()) throw CLIerror(
- "The configuration files MUST contain an [us] section with "
- "appropriate values"
- );
- break;
-
- case 'o':
- if(out!=&cout)
- throw CLIerror("Output file has already been specified");
- out = new ofstream(val.c_str()); // c_str(), really?!?!
- }
- }
-
-
-
- void do_arg(const char *fname) {
- if(log && log!=&cin) delete(log);
- log = 0;
- log = new ifstream(fname);
- ExitCode = do_log();
- }
-
-
-
- // NOTE: the return values isn't really used yet but the channel is here if
- // it can be of use.
- int do_log() {
- int ict=0; // ignored netfilter lines
- std::string l;
-
- /// parse log file ///
-
- if(!config.us.vals.size()) throw CLIerror(
- "A configuration file must be specified before input files."
- );
- line_no=0;
- while(std::getline(*log, l)) {
- line_no++;
- cerr << bug << ' ' << line_no << '\r' << flush;
-
- /// process connections ///
-
- if(analyze.line(l)) {
- if(config.ignores.vals.find(analyze.conn)<0)
- *out << analyze.ln[0] << " " << analyze.ln[1] << " " << analyze.ln[2]
- << " " << analyze.conn << "\n";
- else
- ict++;
- }
- }
- *out << flush; // make sure all data gets written.
- cerr << "Lines: " << line_no
- << "\nIgnored: " << ict
- << "\nTotal rDNS: " << analyze.rdns.size() << endl;
- return 0;
- }
-
-
-
- int main() {
- try {
- cBaseApp::main();
- if(!log) {
- // no inputs were specified run stdin.
- log = &cin;
- ExitCode = do_log();
- }
- } catch(const CLIerror &e) {
- cerr << "ERROR: " << e.what() << "\n";
- help();
- }
- return ExitCode;
- }
-
-
-
- };
-
-
-
- //////////////////////////////////////////////////////////////////////
- // Run it
- //////////////////////////////////////////////////////////////////////
-
- MAIN(IPtraffic)
|