├── LICENSE ├── Makefile ├── README.txt ├── Rules.ini ├── TTFIniManager.cpp ├── TTFIniManager.h ├── TTFPacketCapture.cpp ├── TTFPacketCapture.h ├── TTFRule.h ├── TTFSession.cpp ├── TTFSession.h ├── TTFSessionManager.cpp ├── TTFSessionManager.h ├── dependencies ├── log.cpp ├── log.h └── main.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 tmkk 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | EXEEXT = .exe 2 | TARGET = TinyTCPFirewall$(EXEEXT) 3 | 4 | SOURCES = main.cpp TTFPacketCapture.cpp TTFSessionManager.cpp TTFSession.cpp TTFIniManager.cpp log.cpp 5 | CXXFLAGS = -Wall -O2 -DWINVER=0x501 6 | INCLUDE = 7 | 8 | OBJECTS = $(SOURCES:.cpp=.o) 9 | 10 | all : $(TARGET) 11 | 12 | $(TARGET) : $(OBJECTS) 13 | $(CXX) $(OBJECTS) -o $(TARGET) -lws2_32 -lIphlpapi -static-libgcc -static-libstdc++ 14 | 15 | .SUFFIXES: .cpp .o 16 | .cpp.o: 17 | $(CXX) $(CXXFLAGS) $(INCLUDE) -c $< 18 | 19 | depend: 20 | $(CXX) -MM $(INCLUDE) $(CXXFLAGS) $(SOURCES) > dependencies 21 | 22 | clean : 23 | rm -f $(OBJECTS) $(TARGET) 24 | 25 | include dependencies 26 | 27 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | *これは何?* 2 | WindowsのTCP接続を監視し、特定の条件を満たした場合に切断を行うファイアウォールのようなプログラムです。通常のファイアウォールとは異なり、転送量、転送速度に特化した条件を設定することができます。 3 | 4 | *使い方* 5 | TinyTCPFirewall.exeをダブルクリックして起動します。あとは終了するまで勝手に動作します。動作ログはDOS窓内に表示されるほか、プログラムと同じディレクトリにlog.txtという名前で保存されます。 6 | 7 | *注意* 8 | ・動作には管理者権限が必要です。管理者権限がない場合、起動しません。 9 | ・監視するローカルのIPアドレスは自動検出されますが、NICが複数存在する等の理由で対象としたいアドレスがうまく選ばれない場合、Rules.iniファイルのGlobalセクション内のMyIPAddressキーにIPアドレスを直接指定することができます。 10 | ・OSの環境や設定にもよるかと思いますが、下り(受信)方向の監視については、OSのファイアウォールの例外にこのプログラム(TinyTCPFirewall.exe)を追加しておかないとパケットが降ってこない可能性があります。なお、Windows標準のファイアウォールは実行ファイルのパス指定に%USERPROFILE%などの環境変数が含まれていると正しく機能しないようなので注意してください。 11 | 12 | *ルールの書き方* 13 | 切断の条件を設定するためのルールは、実行ファイルと同じディレクトリにあるRules.iniファイル内に記述します。ルールはRuleで始まるセクション内に記述する必要があります。 14 | 15 | 以下、ルールで使用するキーについて説明します。 16 | 17 | ExeName キー (文字列値, 必須) 18 | 対象とするプログラムのexeファイル名を指定します。大小文字を区別するので注意してください。 19 | 例) ExeName = "foo.exe" 20 | -> foo.exe という実行ファイル名のプログラムを対象とします。 21 | 22 | When キー (整数値, 既定値=0) 23 | ルールを適用するタイミングを通信開始からの秒数で指定します。0を指定した場合、ルールは常時適用されます。0以外の値を指定した場合、ルールが評価されるのはその時間の一度のみです。 24 | 例) When = 10 25 | -> 通信開始から10秒経過した時点でこのルールを適用します。 26 | 27 | ApplyAfter キー (整数値, 既定値=0もしくはGlobalセクションで指定した値) 28 | 通信開始直後にルールを適用しない時間の長さを秒数で指定します。Whenが0の場合に意味を持ち、Whenに0以外の値を指定した場合はこのキーの値は意味を持ちません。Globalセクションにも記述することができ、その場合はキーが存在しない場合の既定値を定義します。 29 | 例) ApplyAfter = 5 30 | -> 通信開始から5秒経過するまで、このルールを適用しません。 31 | 32 | DownloadRateUpper キー (整数値, 既定値=0) 33 | 平均受信速度の上限をKB/s単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 34 | 例) DownloadRateUpper = 100 35 | -> 平均受信速度が 100 KB/s を超過した場合、そのコネクションを切断します。 36 | 37 | DownloadAmountUpper (整数値, 既定値=0) 38 | 受信量の上限をKB単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 39 | 例) DownloadAmountUpper = 1000 40 | -> 受信量が 1000 KB を超過した場合、そのコネクションを切断します。 41 | 42 | DownloadRateLower キー (整数値, 既定値=0) 43 | 平均受信速度の下限をKB/s単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 44 | 例) DownloadRateLower = 100 45 | -> 平均受信速度が 100 KB/s を下回った場合、そのコネクションを切断します。 46 | 47 | DownloadAmountLower (整数値, 既定値=0) 48 | 受信量の下限をKB単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 49 | 例) DownloadAmountLower = 1000 50 | -> 受信量が 1000 KB を下回った場合、そのコネクションを切断します。 51 | 52 | UploadRateUpper キー (整数値, 既定値=0) 53 | 平均送信速度の上限をKB/s単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 54 | 例) UploadRateUpper = 100 55 | -> 平均送信速度が 100 KB/s を超過した場合、そのコネクションを切断します。 56 | 57 | UploadAmountUpper (整数値, 既定値=0) 58 | 送信量の上限をKB単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 59 | 例) UploadAmountUpper = 1000 60 | -> 送信量が 1000 KB を超過した場合、そのコネクションを切断します。 61 | 62 | UploadRateLower キー (整数値, 既定値=0) 63 | 平均送信速度の下限をKB/s単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 64 | 例) UploadRateLower = 100 65 | -> 平均送信速度が 100 KB/s を下回った場合、そのコネクションを切断します。 66 | 67 | UploadAmountLower (整数値, 既定値=0) 68 | 送信量の下限をKB単位で指定します。条件を満たした場合、コネクションは切断されます。0を指定した場合、この条件は無視されます。 69 | 例) UploadAmountLower = 1000 70 | -> 送信量が 1000 KB を下回った場合、そのコネクションを切断します。 71 | 72 | 実際にルールを記述した例を幾つか示します。なお、Amount/Rateの条件を複数指定した場合、各条件のANDが評価されます。 73 | 74 | 例1) hoge.exeで通信開始から5秒で送信速度が250KB/sを上回ったコネクションを切断する 75 | [Rule1] 76 | ExeName = "hoge.exe" 77 | When = 5 78 | UploadRateUpper = 250 79 | 80 | 例2) hoge.exeで総受信量が10000KBを超え、かつ総送信量が1000KB以下のコネクションを切断する 81 | [Rule2] 82 | ExeName = "hoge.exe" 83 | When = 0 84 | DownloadAmountUpper = 10000 85 | UploadAmountLower = 1000 86 | 87 | Whenに0以外を指定する場合は、Rate系のキーで条件を指定するのと、Amount系のキーで指定するのとでは、意味は(ほぼ)同じです。指定しやすい方を使ってください。 88 | 89 | *ブラックリスト* 90 | iniファイルのGlobalセクションにBlackListThresholdというキーがあります。これに0以外の値を指定すると、切断数が指定した回数に達したIPアドレスについてはブラックリストに追加され、以降即時切断されるようになります。ブラックリストに追加されたIPアドレスはログの他にはblacklist.txtというファイルに記録されます。このファイルはPeerBlock等と互換のある形式(説明:開始IPアドレス-終了IPアドレス)になっており、それらのソフトに直接入力として与えることができます。 91 | また、GlobalセクションのLoadBlackListというキーに0以外の値を指定すると、起動時にblacklist.txtの内容でブラックリストを初期化するようになります。これはブラックリストの中身を引き継いで動作させたい場合に便利です。 92 | 93 | *その他のオプション* 94 | DisableCloseButtonキーを0以外の値にすると、閉じるボタンが無効化されます。この場合、Ctrl+Cで終了することができます。 95 | 96 | *配布元* 97 | https://github.com/tmkk/TinyTCPFirewall 98 | -------------------------------------------------------------------------------- /Rules.ini: -------------------------------------------------------------------------------- 1 | [Global] 2 | MyIPAddress = auto 3 | BlackListThreshold = 5 4 | LoadBlackList = 0 5 | DisableCloseButton = 0 6 | 7 | [Rule1] 8 | ExeName = "hoge.exe" 9 | When = 5 10 | UploadRateUpper = 500 11 | 12 | [Rule2] 13 | ExeName = "hoge.exe" 14 | When = 30 15 | UploadRateUpper = 250 16 | -------------------------------------------------------------------------------- /TTFIniManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "TTFIniManager.h" 5 | 6 | void TTFIniManager::parse(void) 7 | { 8 | char iniPath[MAX_PATH], sections[32768]; 9 | sprintf(iniPath,".\\Rules.ini"); 10 | 11 | rules.clear(); 12 | 13 | blackListThreshold = GetPrivateProfileInt("Global","BlackListThreshold",0,iniPath); 14 | int applyAfterGlobal = GetPrivateProfileInt("Global","ApplyAfter",0,iniPath); 15 | disableCloseButton = GetPrivateProfileInt("Global","DisableCloseButton",0,iniPath); 16 | char addrStr[32]; 17 | GetPrivateProfileString("Global","MyIPAddress","",addrStr,32,iniPath); 18 | if(addrStr[0] != 0 && strcasecmp(addrStr,"auto")) { 19 | bool fail = true; 20 | unsigned int num; 21 | char *ptr; 22 | num = strtoul(addrStr,&ptr,10); 23 | if(*ptr++ != '.') goto end; 24 | localAddr = num & 0xff; 25 | num = strtoul(ptr,&ptr,10); 26 | if(*ptr++ != '.') goto end; 27 | localAddr |= (num & 0xff) << 8; 28 | num = strtoul(ptr,&ptr,10); 29 | if(*ptr++ != '.') goto end; 30 | localAddr |= (num & 0xff) << 16; 31 | num = strtoul(ptr,&ptr,10); 32 | localAddr |= (num & 0xff) << 24; 33 | fail = false; 34 | end: 35 | if(fail) localAddr = 0; 36 | //fprintf(stderr,"%d.%d.%d.%d\n",localAddr&0xff,(localAddr >> 8)&0xff,(localAddr >> 16)&0xff,(localAddr >> 24)&0xff); 37 | } 38 | else localAddr = 0; 39 | 40 | blackList.clear(); 41 | int loadBlacklist = GetPrivateProfileInt("Global","LoadBlackList",0,iniPath); 42 | if(loadBlacklist) { 43 | FILE *fp = fopen("blacklist.txt","r"); 44 | if(fp) { 45 | while(fgets(sections,32768,fp)) { 46 | unsigned int start,end; 47 | char *ptr = strchr(sections,':'); 48 | if(!ptr) continue; 49 | start = (strtoul(++ptr,&ptr,10) & 0xff) << 24; 50 | if(*ptr++ != '.') continue; 51 | start |= (strtoul(ptr,&ptr,10) & 0xff) << 16; 52 | if(*ptr++ != '.') continue; 53 | start |= (strtoul(ptr,&ptr,10) & 0xff) << 8; 54 | if(*ptr++ != '.') continue; 55 | start |= strtoul(ptr,&ptr,10) & 0xff; 56 | if(*ptr++ == '-') { 57 | end = (strtoul(ptr,&ptr,10) & 0xff) << 24; 58 | if(*ptr++ != '.') continue; 59 | end |= (strtoul(ptr,&ptr,10) & 0xff) << 16; 60 | if(*ptr++ != '.') continue; 61 | end |= (strtoul(ptr,&ptr,10) & 0xff) << 8; 62 | if(*ptr++ != '.') continue; 63 | end |= strtoul(ptr,&ptr,10) & 0xff; 64 | } 65 | else end = start; 66 | if(start && end) { 67 | if(start == end) blackList.push_back(htonl(start)); 68 | else if(start < end) rangedBlackList.push_back(std::make_pair(start,end)); 69 | } 70 | } 71 | fclose(fp); 72 | } 73 | } 74 | 75 | sections[0] = sections[1] = sections[2] = 0; 76 | GetPrivateProfileString(NULL,NULL,NULL,sections,32768,iniPath); 77 | char section[256]; 78 | int pos=0,len=0; 79 | while(1) { 80 | section[len++] = sections[pos++]; 81 | if(sections[pos] == 0) { 82 | section[len] = 0; 83 | if(!strncasecmp(section,"rule",4)) { 84 | char exeName[MAX_PATH]; 85 | GetPrivateProfileString(section,"ExeName","",exeName,MAX_PATH,iniPath); 86 | if(exeName[0] != 0) { 87 | int direction = 0; 88 | int when = GetPrivateProfileInt(section,"When",0,iniPath); 89 | int applyAfter = GetPrivateProfileInt(section,"ApplyAfter",applyAfterGlobal,iniPath); 90 | int transferRateUpper = GetPrivateProfileInt(section,"TransferRateUpper",0,iniPath); 91 | int transferAmountUpper = GetPrivateProfileInt(section,"TransferAmountUpper",0,iniPath); 92 | int transferRateLower = GetPrivateProfileInt(section,"TransferRateLower",0,iniPath); 93 | int transferAmountLower = GetPrivateProfileInt(section,"TransferAmountLower",0,iniPath); 94 | if(transferRateUpper || transferAmountUpper || transferRateLower || transferAmountLower) { 95 | direction = GetPrivateProfileInt(section,"Direction",0,iniPath); 96 | rules.push_back(PTTFRule(new TTFRule(exeName,direction,when,applyAfter,transferRateUpper,transferAmountUpper,transferRateLower,transferAmountLower))); 97 | } 98 | else { 99 | int uploadRateUpper = GetPrivateProfileInt(section,"UploadRateUpper",0,iniPath); 100 | int uploadAmountUpper = GetPrivateProfileInt(section,"UploadAmountUpper",0,iniPath); 101 | int uploadRateLower = GetPrivateProfileInt(section,"UploadRateLower",0,iniPath); 102 | int uploadAmountLower = GetPrivateProfileInt(section,"UploadAmountLower",0,iniPath); 103 | if(uploadRateUpper || uploadAmountUpper || uploadRateLower || uploadAmountLower) 104 | direction = 1; 105 | int downloadRateUpper = GetPrivateProfileInt(section,"DownloadRateUpper",0,iniPath); 106 | int downloadAmountUpper = GetPrivateProfileInt(section,"DownloadAmountUpper",0,iniPath); 107 | int downloadRateLower = GetPrivateProfileInt(section,"DownloadRateLower",0,iniPath); 108 | int downloadAmountLower = GetPrivateProfileInt(section,"DownloadAmountLower",0,iniPath); 109 | if(downloadRateUpper || downloadAmountUpper || downloadRateLower || downloadAmountLower) { 110 | if(direction) direction = 2; 111 | } 112 | if(direction == 2) 113 | rules.push_back(PTTFRule(new TTFRule(exeName,direction,when,applyAfter,uploadRateUpper,uploadAmountUpper,uploadRateLower,uploadAmountLower,downloadRateUpper,downloadAmountUpper,downloadRateLower,downloadAmountLower))); 114 | else if(direction == 1) 115 | rules.push_back(PTTFRule(new TTFRule(exeName,direction,when,applyAfter,uploadRateUpper,uploadAmountUpper,uploadRateLower,uploadAmountLower))); 116 | else 117 | rules.push_back(PTTFRule(new TTFRule(exeName,direction,when,applyAfter,downloadRateUpper,downloadAmountUpper,downloadRateLower,downloadAmountLower))); 118 | } 119 | } 120 | } 121 | if(sections[pos+1] == 0) break; 122 | pos++; 123 | len = 0; 124 | } 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /TTFIniManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TTFRule.h" 4 | #include 5 | #include 6 | 7 | class TTFIniManager 8 | { 9 | public: 10 | TTFRules rules; 11 | unsigned int localAddr; 12 | int blackListThreshold; 13 | int disableCloseButton; 14 | std::vector blackList; 15 | std::vector > rangedBlackList; 16 | 17 | TTFIniManager():localAddr(0), blackListThreshold(0), disableCloseButton(0) {} 18 | void parse(void); 19 | }; 20 | -------------------------------------------------------------------------------- /TTFPacketCapture.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "TTFPacketCapture.h" 5 | 6 | #define BUFFER_SIZE 65536 7 | 8 | TTFPacketCapture::TTFPacketCapture() : 9 | initialized(false) 10 | { 11 | buffer = new unsigned char[BUFFER_SIZE]; 12 | } 13 | 14 | TTFPacketCapture::~TTFPacketCapture() 15 | { 16 | delete [] buffer; 17 | } 18 | 19 | bool TTFPacketCapture::open(unsigned int addr) 20 | { 21 | if(WSAStartup(MAKEWORD(2, 2), &wsd) != 0) 22 | { 23 | fprintf(stderr, "Error in WSAStartup\n"); 24 | return false; 25 | } 26 | if((socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 27 | { 28 | fprintf(stderr,"Error in WSASocket\n"); 29 | return false; 30 | } 31 | 32 | if(!addr) { 33 | char hostname[NI_MAXHOST + 1] = {'\0'}; 34 | if(gethostname(hostname, sizeof(hostname))) { 35 | fprintf(stderr,"Error in gethostname\n"); 36 | return false; 37 | } 38 | addrinfo hint; 39 | ZeroMemory(&hint, sizeof(hint)); 40 | hint.ai_family = PF_INET; 41 | hint.ai_flags = AI_CANONNAME; 42 | addrinfo* res = 0; 43 | if(getaddrinfo(hostname, 0, &hint, &res)) { 44 | fprintf(stderr,"Error in getaddrinfo\n"); 45 | return false; 46 | } 47 | struct sockaddr_in *sa = (struct sockaddr_in *)(res->ai_addr); 48 | localAddr = sa->sin_addr.s_addr; 49 | } 50 | else localAddr = addr; 51 | 52 | SOCKADDR_IN addr_in; 53 | ZeroMemory(&addr_in, sizeof(addr_in)); 54 | addr_in.sin_addr.s_addr = localAddr; 55 | addr_in.sin_family = AF_INET; 56 | addr_in.sin_port = 0; 57 | if(bind(socket, (SOCKADDR*)&addr_in, sizeof(addr_in)) == SOCKET_ERROR) 58 | { 59 | fprintf(stderr,"Error in bind\n"); 60 | return false; 61 | } 62 | 63 | DWORD ret; 64 | unsigned long optval=1; 65 | if(WSAIoctl(socket, _WSAIOW(IOC_VENDOR, 1), &optval, sizeof(optval), NULL, 0, &ret, NULL, NULL) == SOCKET_ERROR) 66 | { 67 | fprintf(stderr,"Error in WSAIoctl; cannot set socket to promiscuous mode\n"); 68 | return false; 69 | } 70 | 71 | initialized = true; 72 | return true; 73 | } 74 | 75 | bool TTFPacketCapture::read(unsigned char *buf, unsigned int &size) 76 | { 77 | unsigned long length; 78 | unsigned long flags = 0; 79 | WSABUF wsb; 80 | wsb.buf = (char *)buffer; 81 | wsb.len = BUFFER_SIZE; 82 | ZeroMemory(wsb.buf, wsb.len); 83 | 84 | if(WSARecv(socket, &wsb, 1, &length, &flags, NULL, NULL) == SOCKET_ERROR) 85 | { 86 | fprintf(stderr,"Error in WSARecv\n"); 87 | return false; 88 | } 89 | 90 | size = length > size ? size : length; 91 | memcpy(buf, buffer, size); 92 | return true; 93 | } 94 | 95 | void TTFPacketCapture::close(void) 96 | { 97 | if(!initialized) return; 98 | WSACleanup(); 99 | } 100 | -------------------------------------------------------------------------------- /TTFPacketCapture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TTFPacketCapture 6 | { 7 | protected: 8 | SOCKET socket; 9 | WSADATA wsd; 10 | unsigned char *buffer; 11 | bool initialized; 12 | 13 | public: 14 | unsigned int localAddr; 15 | 16 | TTFPacketCapture(); 17 | ~TTFPacketCapture(); 18 | bool open(unsigned int addr); 19 | bool read(unsigned char *buf, unsigned int &size); 20 | void close(void); 21 | }; 22 | -------------------------------------------------------------------------------- /TTFRule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct TTFRule 8 | { 9 | const std::string processName; 10 | int direction; 11 | double when; 12 | double applyAfter; 13 | double transferRateUpper; 14 | unsigned long long transferAmountUpper; 15 | double transferRateLower; 16 | unsigned long long transferAmountLower; 17 | double transferRateUpperAlt; 18 | unsigned long long transferAmountUpperAlt; 19 | double transferRateLowerAlt; 20 | unsigned long long transferAmountLowerAlt; 21 | 22 | TTFRule(std::string &name, int d, double w, double a, double tru, unsigned long long tau, double trl, unsigned long long tal) : 23 | processName(name), direction(d), when(w), applyAfter(a), 24 | transferRateUpper(tru*1024), transferAmountUpper(tau*1024), 25 | transferRateLower(trl*1024), transferAmountLower(tal*1024), 26 | transferRateUpperAlt(0), transferAmountUpperAlt(0), 27 | transferRateLowerAlt(0), transferAmountLowerAlt(0) 28 | {} 29 | TTFRule(std::string &name, int d, double w, double a, double tru, unsigned long long tau, double trl, unsigned long long tal, 30 | double trua, unsigned long long taua, double trla, unsigned long long tala) : 31 | processName(name), direction(d), when(w), applyAfter(a), 32 | transferRateUpper(tru*1024), transferAmountUpper(tau*1024), 33 | transferRateLower(trl*1024), transferAmountLower(tal*1024), 34 | transferRateUpperAlt(trua*1024), transferAmountUpperAlt(taua*1024), 35 | transferRateLowerAlt(trla*1024), transferAmountLowerAlt(tala*1024) 36 | {} 37 | TTFRule(const char *name, int d, double w, double a, double tru, unsigned long long tau, double trl, unsigned long long tal) : 38 | processName(std::string(name)), direction(d), when(w), applyAfter(a), 39 | transferRateUpper(tru*1024), transferAmountUpper(tau*1024), 40 | transferRateLower(trl*1024), transferAmountLower(tal*1024), 41 | transferRateUpperAlt(0), transferAmountUpperAlt(0), 42 | transferRateLowerAlt(0), transferAmountLowerAlt(0) 43 | {} 44 | TTFRule(const char *name, int d, double w, double a, double tru, unsigned long long tau, double trl, unsigned long long tal, 45 | double trua, unsigned long long taua, double trla, unsigned long long tala) : 46 | processName(std::string(name)), direction(d), when(w), applyAfter(a), 47 | transferRateUpper(tru*1024), transferAmountUpper(tau*1024), 48 | transferRateLower(trl*1024), transferAmountLower(tal*1024), 49 | transferRateUpperAlt(trua*1024), transferAmountUpperAlt(taua*1024), 50 | transferRateLowerAlt(trla*1024), transferAmountLowerAlt(tala*1024) 51 | {} 52 | }; 53 | 54 | typedef std::tr1::shared_ptr PTTFRule; 55 | typedef std::vector TTFRules; 56 | -------------------------------------------------------------------------------- /TTFSession.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef _WIN32 3 | #include 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "TTFSession.h" 9 | #include "log.h" 10 | 11 | typedef struct 12 | { 13 | unsigned char verhead; 14 | unsigned char tos; 15 | unsigned short len; 16 | unsigned short id; 17 | unsigned short frag; 18 | unsigned char ttl; 19 | unsigned char prot; 20 | unsigned short chksum; 21 | unsigned int srcip; 22 | unsigned int dstip; 23 | unsigned char data[0]; 24 | } IPHeader; 25 | 26 | TTFSession::TTFSession(unsigned int lAddr, unsigned int lPort, unsigned int rAddr, unsigned int rPort, std::string& pName) : 27 | localAddr(lAddr), localPort(lPort), remoteAddr(rAddr), remotePort(rPort), processName(pName), 28 | bytesSent(0), bytesReceived(0), lastChecked(0) 29 | { 30 | gettimeofday(&monitoringSince,NULL); 31 | } 32 | 33 | double TTFSession::averageUpSpeed(void) 34 | { 35 | struct timeval current; 36 | gettimeofday(¤t, NULL); 37 | double diff = (current.tv_sec - monitoringSince.tv_sec) + (current.tv_usec - monitoringSince.tv_usec) * 1e-6; 38 | 39 | return (double)bytesSent / diff; 40 | } 41 | 42 | double TTFSession::averageDownSpeed(void) 43 | { 44 | struct timeval current; 45 | gettimeofday(¤t, NULL); 46 | double diff = (current.tv_sec - monitoringSince.tv_sec) + (current.tv_usec - monitoringSince.tv_usec) * 1e-6; 47 | 48 | return (double)bytesReceived / diff; 49 | } 50 | 51 | double TTFSession::timeElapsed(void) 52 | { 53 | struct timeval current; 54 | gettimeofday(¤t, NULL); 55 | return (current.tv_sec - monitoringSince.tv_sec) + (current.tv_usec - monitoringSince.tv_usec) * 1e-6; 56 | } 57 | 58 | void TTFSession::commitPacket(unsigned char *data) 59 | { 60 | if(!data) return; 61 | IPHeader *header = (IPHeader *)data; 62 | if(header->srcip == localAddr) 63 | bytesSent += ntohs(header->len); 64 | else if(header->dstip == localAddr) 65 | bytesReceived += ntohs(header->len); 66 | } 67 | 68 | void TTFSession::disconnect() 69 | { 70 | #ifdef _WIN32 71 | MIB_TCPROW session; 72 | session.dwLocalAddr = localAddr; 73 | session.dwLocalPort = htons(localPort); 74 | session.dwRemoteAddr = remoteAddr; 75 | session.dwRemotePort = htons(remotePort); 76 | session.dwState = MIB_TCP_STATE_DELETE_TCB; 77 | SetTcpEntry(&session); 78 | #endif 79 | log_dated_printf(" (%s)\n Closed connection %d.%d.%d.%d:%d <--> %d.%d.%d.%d:%d\n",processName.c_str(),localAddr&0xff,(localAddr >> 8)&0xff,(localAddr >> 16)&0xff,(localAddr >> 24)&0xff,localPort,remoteAddr&0xff,(remoteAddr >> 8)&0xff,(remoteAddr >> 16)&0xff,(remoteAddr >> 24)&0xff,remotePort); 80 | } 81 | 82 | void TTFSession::status() 83 | { 84 | fprintf(stderr,"* %d.%d.%d.%d:%d <--> %d.%d.%d.%d:%d [%s]\n",localAddr&0xff,(localAddr >> 8)&0xff,(localAddr >> 16)&0xff,(localAddr >> 24)&0xff,localPort,remoteAddr&0xff,(remoteAddr >> 8)&0xff,(remoteAddr >> 16)&0xff,(remoteAddr >> 24)&0xff,remotePort,processName.c_str()); 85 | double downSpeed = this->averageDownSpeed(); 86 | double upSpeed = this->averageUpSpeed(); 87 | if(bytesReceived >= 1024*1024) { 88 | fprintf(stderr," %.1f MB received ",bytesReceived/1024.0/1024.0); 89 | } 90 | else { 91 | fprintf(stderr," %.1f KB received ",bytesReceived/1024.0); 92 | } 93 | if(downSpeed >= 1024.0 * 1024.0) { 94 | fprintf(stderr,"(%.1f MB/s), ",downSpeed/1024.0/1024.0); 95 | } 96 | else { 97 | fprintf(stderr,"(%.1f KB/s), ",downSpeed/1024.0); 98 | } 99 | if(bytesSent >= 1024*1024) { 100 | fprintf(stderr,"%.1f MB sent ",bytesSent/1024.0/1024.0); 101 | } 102 | else { 103 | fprintf(stderr,"%.1f KB sent ",bytesSent/1024.0); 104 | } 105 | if(upSpeed >= 1024.0 * 1024.0) { 106 | fprintf(stderr,"(%.1f MB/s)\n",upSpeed/1024.0/1024.0); 107 | } 108 | else { 109 | fprintf(stderr,"(%.1f KB/s)\n",upSpeed/1024.0); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /TTFSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class TTFSession 8 | { 9 | public: 10 | const unsigned int localAddr; 11 | const unsigned int localPort; 12 | const unsigned int remoteAddr; 13 | const unsigned int remotePort; 14 | const std::string processName; 15 | 16 | unsigned long long bytesSent; 17 | unsigned long long bytesReceived; 18 | double lastChecked; 19 | 20 | protected: 21 | struct timeval monitoringSince; 22 | 23 | public: 24 | TTFSession(unsigned int lAddr, unsigned int lPort, unsigned int rAddr, unsigned int rPort, std::string& pName); 25 | 26 | double averageUpSpeed(void); 27 | double averageDownSpeed(void); 28 | double timeElapsed(void); 29 | void commitPacket(unsigned char *data); 30 | void disconnect(void); 31 | void status(void); 32 | }; 33 | 34 | typedef std::tr1::shared_ptr PTTFSession; 35 | -------------------------------------------------------------------------------- /TTFSessionManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #ifdef _WIN32 5 | #include 6 | #include 7 | #include 8 | #else 9 | #include 10 | #endif 11 | #include "TTFSessionManager.h" 12 | #include "log.h" 13 | 14 | typedef struct 15 | { 16 | unsigned char verhead; 17 | unsigned char tos; 18 | unsigned short len; 19 | unsigned short id; 20 | unsigned short frag; 21 | unsigned char ttl; 22 | unsigned char prot; 23 | unsigned short chksum; 24 | unsigned int srcip; 25 | unsigned int dstip; 26 | unsigned char data[0]; 27 | } IPHeader; 28 | 29 | typedef struct 30 | { 31 | unsigned short sport; 32 | unsigned short dport; 33 | unsigned long seq; 34 | unsigned long ack; 35 | unsigned char hlr; 36 | unsigned char rfl; 37 | unsigned short win; 38 | unsigned short sum; 39 | unsigned short urp; 40 | } TCPHeader; 41 | 42 | TTFSessionManager::TTFSessionManager(unsigned int lAddr, int threshold) : 43 | localAddr(lAddr), blackListThreshold(threshold) 44 | { 45 | sessionList = new TTFSessionList(); 46 | } 47 | 48 | TTFSessionManager::~TTFSessionManager() 49 | { 50 | delete sessionList; 51 | } 52 | 53 | void TTFSessionManager::addRule(PTTFRule rule) 54 | { 55 | rules.push_back(rule); 56 | targetProcessList.insert(rule->processName); 57 | } 58 | 59 | void TTFSessionManager::addBlacklistedAddress(unsigned int address) 60 | { 61 | blackList.insert(address); 62 | } 63 | 64 | void TTFSessionManager::addRangedBlacklistedAddress(unsigned int start, unsigned int end) 65 | { 66 | rangedBlackList.push_back(std::make_pair(start,end)); 67 | } 68 | 69 | void TTFSessionManager::commitPacket(unsigned char *data) 70 | { 71 | if(sessionList->empty()) return; 72 | IPHeader *header = (IPHeader *)data; 73 | if(header->prot == 6 && header->dstip != 0 && header->srcip != 0) { 74 | TCPHeader *tcpHeader = (TCPHeader *)(data + 4*(header->verhead & 0xf)); 75 | unsigned short sport = ntohs(tcpHeader->sport); 76 | unsigned short dport = ntohs(tcpHeader->dport); 77 | if(header->srcip == localAddr) { 78 | if(sport && dport) { 79 | unsigned long long key = ((unsigned long long)sport << 48) | ((unsigned long long)(header->dstip) << 16) | dport; 80 | TTFSessionList::iterator it = sessionList->find(key); 81 | if(it != sessionList->end()) { 82 | //fprintf(stderr,"committing outgoing packet\n"); 83 | it->second->commitPacket(data); 84 | } 85 | } 86 | } 87 | else if(header->dstip == localAddr) { 88 | if(sport && dport) { 89 | unsigned long long key = ((unsigned long long)dport << 48) | ((unsigned long long)(header->srcip) << 16) | sport; 90 | TTFSessionList::iterator it = sessionList->find(key); 91 | if(it != sessionList->end()) { 92 | //fprintf(stderr,"committing incoming packet\n"); 93 | it->second->commitPacket(data); 94 | } 95 | } 96 | } 97 | 98 | } 99 | } 100 | 101 | #ifdef _WIN32 102 | bool TTFSessionManager::applyBlackListFilter(MIB_TCPROW_OWNER_PID *table) 103 | { 104 | if(blackList.empty() || blackList.find(table->dwRemoteAddr) == blackList.end()) { 105 | if(rangedBlackList.empty()) return false; 106 | std::vector >::iterator it = rangedBlackList.begin(); 107 | unsigned int addr = ntohl(table->dwRemoteAddr); 108 | while(it != rangedBlackList.end()) { 109 | if(addr >= it->first && addr <= it->second) goto found; 110 | it++; 111 | } 112 | return false; 113 | } 114 | found: 115 | MIB_TCPROW session; 116 | session.dwLocalAddr = table->dwLocalAddr; 117 | session.dwLocalPort = table->dwLocalPort; 118 | session.dwRemoteAddr = table->dwRemoteAddr; 119 | session.dwRemotePort = table->dwRemotePort; 120 | session.dwState = MIB_TCP_STATE_DELETE_TCB; 121 | SetTcpEntry(&session); 122 | 123 | log_dated_printf("\n Blocked connection from blacklisted address %ld.%ld.%ld.%ld\n",table->dwRemoteAddr&0xff,(table->dwRemoteAddr >> 8)&0xff,(table->dwRemoteAddr >> 16)&0xff,(table->dwRemoteAddr >> 24)&0xff); 124 | return true; 125 | } 126 | #endif 127 | 128 | void TTFSessionManager::updateTargetSessions(void) 129 | { 130 | if(targetProcessList.empty()) return; 131 | if(targetPids.empty()) { 132 | //fprintf(stderr,"No process to monitor\n"); 133 | sessionList->clear(); 134 | return; 135 | } 136 | #ifdef _WIN32 137 | HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 138 | if(hProcessSnap == INVALID_HANDLE_VALUE) { 139 | fprintf(stderr,"Failed to take process snapshot."); 140 | return; 141 | } 142 | PROCESSENTRY32 processEntry; 143 | processEntry.dwSize = sizeof(processEntry); 144 | if(!Process32First(hProcessSnap, &processEntry)) { 145 | fprintf(stderr,"Process32First returned error\n"); 146 | return; 147 | } 148 | do { 149 | std::set::iterator it = targetProcessList.begin(); 150 | while(it != targetProcessList.end()) { 151 | if(it->compare(processEntry.szExeFile) == 0) { 152 | targetPids.insert(std::make_pair(processEntry.th32ProcessID,*it)); 153 | } 154 | it++; 155 | } 156 | } while(Process32Next(hProcessSnap, &processEntry)); 157 | CloseHandle(hProcessSnap); 158 | 159 | if(targetPids.empty()) { 160 | //fprintf(stderr,"No process to monitor\n"); 161 | return; 162 | } 163 | 164 | DWORD Size=0; 165 | if(ERROR_INSUFFICIENT_BUFFER == GetExtendedTcpTable(NULL,&Size,TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL,0)){ 166 | MIB_TCPTABLE_OWNER_PID *tcp = (PMIB_TCPTABLE_OWNER_PID) new char[Size]; 167 | if(NO_ERROR == GetExtendedTcpTable(tcp,&Size,TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL,0)){ 168 | TTFSessionList *newSessionList = new TTFSessionList(); 169 | for(unsigned int i=0; idwNumEntries; i++) { 170 | std::map::iterator it = targetPids.find(tcp->table[i].dwOwningPid); 171 | if(it != targetPids.end()) { 172 | unsigned int laddr = tcp->table[i].dwLocalAddr; 173 | unsigned short lport = ntohs(tcp->table[i].dwLocalPort); 174 | unsigned int raddr = tcp->table[i].dwRemoteAddr; 175 | unsigned short rport = ntohs(tcp->table[i].dwRemotePort); 176 | if(laddr != localAddr || !lport || !raddr || !rport) continue; 177 | if(this->applyBlackListFilter(&tcp->table[i])) continue; 178 | unsigned long long key = ((unsigned long long)lport << 48) | ((unsigned long long)raddr << 16) | rport; 179 | TTFSessionList::iterator it2 = sessionList->find(key); 180 | if(it2 == sessionList->end()) { 181 | PTTFSession session(new TTFSession(localAddr,lport,raddr,rport,it->second)); 182 | newSessionList->insert(std::make_pair(key,session)); 183 | } 184 | else { 185 | newSessionList->insert(std::make_pair(key,it2->second)); 186 | } 187 | } 188 | } 189 | TTFSessionList *oldSessionList = sessionList; 190 | sessionList = newSessionList; 191 | delete oldSessionList; 192 | } 193 | else { 194 | fprintf(stderr,"GetExtendedTcpTable returned error\n"); 195 | } 196 | delete [] tcp; 197 | } 198 | else { 199 | fprintf(stderr,"GetExtendedTcpTable returned error\n"); 200 | } 201 | #endif 202 | } 203 | 204 | void TTFSessionManager::updateTargetProcessPid(void) 205 | { 206 | if(targetProcessList.empty()) return; 207 | targetPids.clear(); 208 | 209 | #ifdef _WIN32 210 | HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 211 | if(hProcessSnap == INVALID_HANDLE_VALUE) { 212 | fprintf(stderr,"Failed to take process snapshot."); 213 | return; 214 | } 215 | PROCESSENTRY32 processEntry; 216 | processEntry.dwSize = sizeof(processEntry); 217 | if(!Process32First(hProcessSnap, &processEntry)) { 218 | fprintf(stderr,"Process32First returned error\n"); 219 | return; 220 | } 221 | do { 222 | std::set::iterator it = targetProcessList.begin(); 223 | while(it != targetProcessList.end()) { 224 | if(it->compare(processEntry.szExeFile) == 0) { 225 | targetPids.insert(std::make_pair(processEntry.th32ProcessID,*it)); 226 | } 227 | it++; 228 | } 229 | } while(Process32Next(hProcessSnap, &processEntry)); 230 | CloseHandle(hProcessSnap); 231 | #endif 232 | } 233 | 234 | void TTFSessionManager::registerToBlackList(PTTFSession session, PTTFRule rule) 235 | { 236 | if(!blackListThreshold) return; 237 | std::map::iterator it = blockedAddrs.find(session->remoteAddr); 238 | bool added = false; 239 | if(it != blockedAddrs.end()) { 240 | if(++it->second >= blackListThreshold) { 241 | blackList.insert(it->first); 242 | blockedAddrs.erase(it); 243 | added = true; 244 | } 245 | } 246 | else { 247 | if(blackListThreshold == 1) { 248 | blackList.insert(session->remoteAddr); 249 | added = true; 250 | } 251 | else blockedAddrs.insert(std::make_pair(session->remoteAddr,1)); 252 | } 253 | if(added) { 254 | char ruleStr[256]; 255 | char addrStr[32]; 256 | snprintf(addrStr,32,"%d.%d.%d.%d",session->remoteAddr&0xff,(session->remoteAddr >> 8)&0xff,(session->remoteAddr >> 16)&0xff,(session->remoteAddr >> 24)&0xff); 257 | log_dated_printf(" Added %s to blacklist\n",addrStr); 258 | snprintf(ruleStr,256,"When=%d",(int)rule->when); 259 | if(rule->direction == 2) { 260 | if(rule->transferRateUpperAlt) snprintf(ruleStr,256,"%s DownRate>%d",ruleStr,(int)(rule->transferRateUpperAlt/1024)); 261 | if(rule->transferAmountUpperAlt) snprintf(ruleStr,256,"%s DownAmount>%d",ruleStr,(int)(rule->transferAmountUpperAlt/1024)); 262 | if(rule->transferRateLowerAlt) snprintf(ruleStr,256,"%s DownRate<%d",ruleStr,(int)(rule->transferRateLowerAlt/1024)); 263 | if(rule->transferAmountLowerAlt) snprintf(ruleStr,256,"%s DownAmount<%d",ruleStr,(int)(rule->transferAmountLowerAlt/1024)); 264 | if(rule->transferRateUpper) snprintf(ruleStr,256,"%s UpRate>%d",ruleStr,(int)(rule->transferRateUpper/1024)); 265 | if(rule->transferAmountUpper) snprintf(ruleStr,256,"%s UpAmount>%d",ruleStr,(int)(rule->transferAmountUpper/1024)); 266 | if(rule->transferRateLower) snprintf(ruleStr,256,"%s UpRate<%d",ruleStr,(int)(rule->transferRateLower/1024)); 267 | if(rule->transferAmountLower) snprintf(ruleStr,256,"%s UpAmount<%d",ruleStr,(int)(rule->transferAmountLower/1024)); 268 | } 269 | else if(rule->direction == 1) { 270 | if(rule->transferRateUpper) snprintf(ruleStr,256,"%s UpRate>%d",ruleStr,(int)(rule->transferRateUpper/1024)); 271 | if(rule->transferAmountUpper) snprintf(ruleStr,256,"%s UpAmount>%d",ruleStr,(int)(rule->transferAmountUpper/1024)); 272 | if(rule->transferRateLower) snprintf(ruleStr,256,"%s UpRate<%d",ruleStr,(int)(rule->transferRateLower/1024)); 273 | if(rule->transferAmountLower) snprintf(ruleStr,256,"%s UpAmount<%d",ruleStr,(int)(rule->transferAmountLower/1024)); 274 | } 275 | else { 276 | if(rule->transferRateUpper) snprintf(ruleStr,256,"%s DownRate>%d",ruleStr,(int)(rule->transferRateUpper/1024)); 277 | if(rule->transferAmountUpper) snprintf(ruleStr,256,"%s DownAmount>%d",ruleStr,(int)(rule->transferAmountUpper/1024)); 278 | if(rule->transferRateLower) snprintf(ruleStr,256,"%s DownRate<%d",ruleStr,(int)(rule->transferRateLower/1024)); 279 | if(rule->transferAmountLower) snprintf(ruleStr,256,"%s DownAmount<%d",ruleStr,(int)(rule->transferAmountLower/1024)); 280 | } 281 | log_blacklist("[%s] %s:%s-%s\n",session->processName.c_str(),ruleStr,addrStr,addrStr); 282 | } 283 | } 284 | 285 | void TTFSessionManager::applyFilters(void) 286 | { 287 | if(sessionList->empty()) return; 288 | if(rules.empty()) return; 289 | 290 | TTFSessionList::iterator it = sessionList->begin(); 291 | while(it != sessionList->end()) { 292 | PTTFSession session = it->second; 293 | TTFRules::iterator it2 = rules.begin(); 294 | double elapsed = session->timeElapsed(); 295 | while(it2 != rules.end()) { 296 | PTTFRule rule = *it2; 297 | if((rule->when == 0 && elapsed >= rule->applyAfter) || (rule->when > session->lastChecked && elapsed >= rule->when)) { 298 | if(rule->processName.compare(session->processName) == 0) { 299 | int disconnect = 0; 300 | double transferRate; 301 | unsigned long long transferAmount; 302 | double transferRateAlt = 0; 303 | unsigned long long transferAmountAlt = 0; 304 | if(rule->direction == 2) { 305 | transferRate = session->averageUpSpeed(); 306 | transferAmount = session->bytesSent; 307 | transferRateAlt = session->averageDownSpeed(); 308 | transferAmountAlt = session->bytesReceived; 309 | if(rule->transferRateUpper) { 310 | if(transferRate >= rule->transferRateUpper) disconnect = 1; 311 | else disconnect = -1; 312 | } 313 | if(rule->transferAmountUpper && disconnect >= 0) { 314 | if(transferAmount >= rule->transferAmountUpper) disconnect = 1; 315 | else disconnect = -1; 316 | } 317 | if(rule->transferRateLower && disconnect >= 0) { 318 | if(transferRate < rule->transferRateLower) disconnect = 1; 319 | else disconnect = -1; 320 | } 321 | if(rule->transferAmountLower && disconnect >= 0) { 322 | if(transferAmount < rule->transferAmountLower) disconnect = 1; 323 | else disconnect = -1; 324 | } 325 | if(rule->transferRateUpperAlt && disconnect >= 0) { 326 | if(transferRateAlt >= rule->transferRateUpperAlt) disconnect = 1; 327 | else disconnect = -1; 328 | } 329 | if(rule->transferAmountUpperAlt && disconnect >= 0) { 330 | if(transferAmountAlt >= rule->transferAmountUpperAlt) disconnect = 1; 331 | else disconnect = -1; 332 | } 333 | if(rule->transferRateLowerAlt && disconnect >= 0) { 334 | if(transferRateAlt < rule->transferRateLowerAlt) disconnect = 1; 335 | else disconnect = -1; 336 | } 337 | if(rule->transferAmountLowerAlt && disconnect >= 0) { 338 | if(transferAmountAlt < rule->transferAmountLowerAlt) disconnect = 1; 339 | else disconnect = -1; 340 | } 341 | } 342 | else { 343 | if(rule->direction == 0) { // down 344 | transferRate = session->averageDownSpeed(); 345 | transferAmount = session->bytesReceived; 346 | } 347 | else { // up 348 | transferRate = session->averageUpSpeed(); 349 | transferAmount = session->bytesSent; 350 | } 351 | if(rule->transferRateUpper) { 352 | if(transferRate >= rule->transferRateUpper) disconnect = 1; 353 | else disconnect = -1; 354 | } 355 | if(rule->transferAmountUpper && disconnect >= 0) { 356 | if(transferAmount >= rule->transferAmountUpper) disconnect = 1; 357 | else disconnect = -1; 358 | } 359 | if(rule->transferRateLower && disconnect >= 0) { 360 | if(transferRate < rule->transferRateLower) disconnect = 1; 361 | else disconnect = -1; 362 | } 363 | if(rule->transferAmountLower && disconnect >= 0) { 364 | if(transferAmount < rule->transferAmountLower) disconnect = 1; 365 | else disconnect = -1; 366 | } 367 | } 368 | if(disconnect > 0) { 369 | session->disconnect(); 370 | if(transferAmount >= 1024*1024) { 371 | log_printf(" Reason: %.2f MB %s in %.1f seconds ",transferAmount/1024.0/1024.0,rule->direction?"sent":"received",elapsed); 372 | } 373 | else { 374 | log_printf(" Reason: %.1f KB %s in %.1f seconds ",transferAmount/1024.0,rule->direction?"sent":"received",elapsed); 375 | } 376 | if(transferRate >= 1024.0 * 1024.0) { 377 | log_printf("(%.2f MB/s)\n",transferRate/1024.0/1024.0); 378 | } 379 | else { 380 | log_printf("(%.1f KB/s)\n",transferRate/1024.0); 381 | } 382 | if(rule->direction == 2) { 383 | if(transferAmountAlt >= 1024*1024) { 384 | log_printf(" %.2f MB received in %.1f seconds ",transferAmountAlt/1024.0/1024.0,elapsed); 385 | } 386 | else { 387 | log_printf(" %.1f KB received in %.1f seconds ",transferAmountAlt/1024.0,elapsed); 388 | } 389 | if(transferRateAlt >= 1024.0 * 1024.0) { 390 | log_printf("(%.2f MB/s)\n",transferRateAlt/1024.0/1024.0); 391 | } 392 | else { 393 | log_printf("(%.1f KB/s)\n",transferRateAlt/1024.0); 394 | } 395 | } 396 | this->registerToBlackList(session,rule); 397 | } 398 | } 399 | } 400 | it2++; 401 | } 402 | session->lastChecked = elapsed; 403 | it++; 404 | } 405 | } 406 | 407 | void TTFSessionManager::printTargetSessionsState(void) 408 | { 409 | if(sessionList->empty()) { 410 | fprintf(stderr,"No sessions to monitor.\n"); 411 | return; 412 | } 413 | TTFSessionList::iterator it = sessionList->begin(); 414 | while(it != sessionList->end()) { 415 | it->second->status(); 416 | it++; 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /TTFSessionManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifdef _WIN32 9 | #include 10 | #endif 11 | #include "TTFSession.h" 12 | #include "TTFRule.h" 13 | typedef std::map TTFSessionList; 14 | 15 | class TTFSessionManager 16 | { 17 | protected: 18 | const unsigned int localAddr; 19 | TTFSessionList *sessionList; 20 | std::set targetProcessList; 21 | std::map targetPids; 22 | std::map blockedAddrs; 23 | std::set blackList; 24 | std::vector > rangedBlackList; 25 | int blackListThreshold; 26 | TTFRules rules; 27 | 28 | public: 29 | TTFSessionManager(unsigned int lAddr, int threshold); 30 | ~TTFSessionManager(); 31 | 32 | void commitPacket(unsigned char *data); 33 | void addRule(PTTFRule rule); 34 | void addBlacklistedAddress(unsigned int address); 35 | void addRangedBlacklistedAddress(unsigned int start, unsigned int end); 36 | void updateTargetSessions(void); 37 | void updateTargetProcessPid(void); 38 | void applyFilters(void); 39 | void printTargetSessionsState(void); 40 | private: 41 | void registerToBlackList(PTTFSession session, PTTFRule rule); 42 | #ifdef _WIN32 43 | bool applyBlackListFilter(MIB_TCPROW_OWNER_PID *table); 44 | #endif 45 | }; -------------------------------------------------------------------------------- /dependencies: -------------------------------------------------------------------------------- 1 | main.o: main.cpp TTFPacketCapture.h TTFSessionManager.h TTFSession.h \ 2 | TTFRule.h TTFIniManager.h log.h 3 | TTFPacketCapture.o: TTFPacketCapture.cpp TTFPacketCapture.h 4 | TTFSessionManager.o: TTFSessionManager.cpp TTFSessionManager.h \ 5 | TTFSession.h TTFRule.h log.h 6 | TTFSession.o: TTFSession.cpp TTFSession.h log.h 7 | TTFIniManager.o: TTFIniManager.cpp TTFIniManager.h TTFRule.h 8 | log.o: log.cpp log.h 9 | -------------------------------------------------------------------------------- /log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "log.h" 5 | 6 | void log_printf(const char *format ...) 7 | { 8 | va_list argp; 9 | va_start(argp, format); 10 | vfprintf(stderr, format, argp); 11 | va_end(argp); 12 | 13 | FILE *fp = fopen("log.txt","a"); 14 | if(!fp) return; 15 | va_start(argp, format); 16 | vfprintf(fp, format, argp); 17 | va_end(argp); 18 | fclose(fp); 19 | } 20 | 21 | void log_dated_printf(const char *format ...) 22 | { 23 | char timeStr[32]; 24 | time_t t; 25 | time(&t); 26 | struct tm *tm =localtime(&t); 27 | strftime(timeStr, 32, "%Y/%m/%d %H:%M:%S", tm); 28 | 29 | fprintf(stderr,"[%s]",timeStr); 30 | va_list argp; 31 | va_start(argp, format); 32 | vfprintf(stderr, format, argp); 33 | va_end(argp); 34 | 35 | FILE *fp = fopen("log.txt","a"); 36 | if(!fp) return; 37 | fprintf(fp,"[%s]",timeStr); 38 | va_start(argp, format); 39 | vfprintf(fp, format, argp); 40 | va_end(argp); 41 | fclose(fp); 42 | } 43 | 44 | void log_blacklist(const char *format ...) 45 | { 46 | FILE *fp = fopen("blacklist.txt","a"); 47 | if(!fp) return; 48 | va_list argp; 49 | va_start(argp, format); 50 | vfprintf(fp, format, argp); 51 | va_end(argp); 52 | fclose(fp); 53 | } 54 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void log_printf(const char *format ...); 5 | void log_dated_printf(const char *format ...); 6 | void log_blacklist(const char *format ...); 7 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "TTFPacketCapture.h" 2 | #include "TTFSessionManager.h" 3 | #include "TTFRule.h" 4 | #include "TTFIniManager.h" 5 | #include "log.h" 6 | #include 7 | #include 8 | #include 9 | 10 | BOOL WINAPI exitHandler(DWORD dwCtrlType) 11 | { 12 | switch (dwCtrlType) { 13 | case CTRL_C_EVENT: 14 | if(IDCANCEL == MessageBox(NULL,"Are you sure you want to quit?","Quit application",MB_OKCANCEL|MB_ICONWARNING)) 15 | return TRUE; 16 | break; 17 | default: 18 | break; 19 | } 20 | 21 | return FALSE; 22 | } 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | SetConsoleCtrlHandler(exitHandler, TRUE); 27 | 28 | unsigned char buffer[65536]; 29 | TTFPacketCapture capture; 30 | TTFIniManager ini; 31 | ini.parse(); 32 | 33 | if(!capture.open(ini.localAddr)) { 34 | fprintf(stderr,"Socket initialization error\n"); 35 | MessageBox(NULL,"Invalid IP Address, or run with administrator privilege.","Socket initialization error",MB_OK|MB_ICONSTOP); 36 | return -1; 37 | } 38 | 39 | log_dated_printf(" Started program\n"); 40 | 41 | struct timeval tv1,tv2; 42 | TTFSessionManager manager(capture.localAddr, ini.blackListThreshold); 43 | 44 | if(ini.disableCloseButton) { 45 | HMENU hmenu = GetSystemMenu(GetConsoleWindow(), FALSE); 46 | RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); 47 | } 48 | 49 | TTFRules::iterator it = ini.rules.begin(); 50 | while(it != ini.rules.end()) { 51 | manager.addRule(*it++); 52 | } 53 | 54 | log_dated_printf(" Read %d rule%s\n",ini.rules.size(),ini.rules.size() > 1 ? "s" : ""); 55 | 56 | if(!ini.blackList.empty()) { 57 | std::vector::iterator it2 = ini.blackList.begin(); 58 | while(it2 != ini.blackList.end()) { 59 | manager.addBlacklistedAddress(*it2++); 60 | } 61 | log_dated_printf(" Added %d address%s to blacklist\n",ini.blackList.size(),ini.blackList.size() > 1 ? "es" : ""); 62 | } 63 | 64 | if(!ini.rangedBlackList.empty()) { 65 | std::vector >::iterator it3 = ini.rangedBlackList.begin(); 66 | while(it3 != ini.rangedBlackList.end()) { 67 | manager.addRangedBlacklistedAddress(it3->first,it3->second); 68 | it3++; 69 | } 70 | log_dated_printf(" Added %d address range%s to blacklist\n",ini.rangedBlackList.size(),ini.rangedBlackList.size() > 1 ? "s" : ""); 71 | } 72 | 73 | manager.updateTargetProcessPid(); 74 | manager.updateTargetSessions(); 75 | 76 | log_dated_printf(" Started monitoring %d.%d.%d.%d\n",capture.localAddr&0xff,(capture.localAddr >> 8)&0xff,(capture.localAddr >> 16)&0xff,(capture.localAddr >> 24)&0xff); 77 | 78 | gettimeofday(&tv1,NULL); 79 | while(1) { 80 | unsigned int length = 1024; 81 | if(capture.read(buffer,length) == false) 82 | { 83 | fprintf(stderr,"Error while reading socket\n"); 84 | break; 85 | } 86 | manager.commitPacket(buffer); 87 | gettimeofday(&tv2,NULL); 88 | double elapsed = tv2.tv_sec-tv1.tv_sec+(tv2.tv_usec-tv1.tv_usec)*1e-6; 89 | if(elapsed > 1.0) { 90 | manager.applyFilters(); 91 | manager.updateTargetProcessPid(); 92 | manager.updateTargetSessions(); 93 | //manager.printTargetSessionsState(); 94 | gettimeofday(&tv1,NULL); 95 | } 96 | 97 | } 98 | 99 | capture.close(); 100 | 101 | return 0; 102 | } 103 | --------------------------------------------------------------------------------