@roflsec/fail2scan 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/daemon.js +41 -19
- package/package.json +1 -1
package/bin/daemon.js
CHANGED
|
@@ -8,18 +8,23 @@ require('dotenv').config({ quiet:true})
|
|
|
8
8
|
|
|
9
9
|
// -------------------- IPGeolocation --------------------
|
|
10
10
|
let getGeo = async (ip) => null;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const GeolocationParams = require("ip-geolocation-api-javascript-sdk
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
getGeo = (ip) => {
|
|
17
|
-
|
|
18
|
-
const params = new GeolocationParams();
|
|
11
|
+
|
|
12
|
+
if (process.env.IPGEO_API_KEY) {
|
|
13
|
+
const { IPGeolocationAPI, GeolocationParams } = require("ip-geolocation-api-javascript-sdk");
|
|
14
|
+
const geoApi = new IPGeolocationAPI(new GeolocationParams({ apiKey: process.env.IPGEO_API_KEY }));
|
|
15
|
+
|
|
16
|
+
getGeo = async (ip) => {
|
|
17
|
+
try {
|
|
18
|
+
const params = new GeolocationParams({ apiKey: process.env.IPGEO_API_KEY });
|
|
19
19
|
params.setIPAddress(ip);
|
|
20
20
|
params.setFields("geo,time_zone,currency,asn,security");
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
return await new Promise((resolve, reject) => {
|
|
23
|
+
geoApi.getGeolocation(resolve, reject, params);
|
|
24
|
+
});
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
23
28
|
};
|
|
24
29
|
}
|
|
25
30
|
|
|
@@ -64,7 +69,14 @@ function saveState(s){try{fs.mkdirSync(path.dirname(STATE_FILE),{recursive:true,
|
|
|
64
69
|
const STATE=loadState();
|
|
65
70
|
|
|
66
71
|
// -------------------- IP extraction --------------------
|
|
67
|
-
function extractIpFromLine(line){
|
|
72
|
+
function extractIpFromLine(line){
|
|
73
|
+
// garde ton extracteur d’origine (IPv4 + IPv6)
|
|
74
|
+
const v4 = line.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/);
|
|
75
|
+
if(v4&&v4[0]) return v4[0];
|
|
76
|
+
const v6 = line.match(/\b([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}\b/);
|
|
77
|
+
if(v6&&v6[0]) return v6[0];
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
68
80
|
|
|
69
81
|
// -------------------- nmap helpers (parallel support) --------------------
|
|
70
82
|
function spawnOneNmap(args, outFile) {
|
|
@@ -153,20 +165,17 @@ async function performScan(ip){
|
|
|
153
165
|
|
|
154
166
|
try{ fs.writeFileSync(path.join(outDir,'summary.json'),JSON.stringify(summary,null,2)); } catch (e) {}
|
|
155
167
|
|
|
156
|
-
// geo non bloquant
|
|
157
168
|
if(process.env.IPGEO_API_KEY){
|
|
158
169
|
getGeo(ip)
|
|
159
|
-
.then(geo => {
|
|
160
|
-
|
|
161
|
-
})
|
|
162
|
-
.catch(e=>{});
|
|
170
|
+
.then(geo => { try{ fs.writeFileSync(path.join(outDir,'geo.json'), JSON.stringify(geo, null, 2)); }catch{} })
|
|
171
|
+
.catch(()=>{});
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
try{ fs.chmodSync(outDir,0o750); } catch (e) {}
|
|
166
175
|
log('Scan written for',ip,'->',outDir);
|
|
167
176
|
}
|
|
168
177
|
|
|
169
|
-
// -------------------- queue
|
|
178
|
+
// -------------------- queue --------------------
|
|
170
179
|
class ScanQueue{
|
|
171
180
|
constructor(concurrency=1){this.concurrency=concurrency;this.running=0;this.q=[];this.set=STATE.seen;this.tmpCache=new Set();}
|
|
172
181
|
push(ip){
|
|
@@ -200,7 +209,9 @@ const concurrency = CORE_OVERRIDE||USER_CONCURRENCY||os.cpus().length||1;
|
|
|
200
209
|
const q = new ScanQueue(concurrency);
|
|
201
210
|
log(`Fail2Scan started. Watching ${LOG_PATH} -> output ${OUT_ROOT}, concurrency ${concurrency}`);
|
|
202
211
|
|
|
203
|
-
|
|
212
|
+
// -------------------- FIX : regex BAN correct --------------------
|
|
213
|
+
const BAN_RE = /Ban\s+(\d{1,3}(?:\.\d{1,3}){3})/;
|
|
214
|
+
|
|
204
215
|
class FileTail{
|
|
205
216
|
constructor(filePath,onLine){this.filePath=filePath;this.onLine=onLine;this.pos=0;this.inode=null;this.buf='';this.watch=null;this.start();}
|
|
206
217
|
start(){try{const st=fs.statSync(this.filePath);this.inode=st.ino;this.pos=st.size;}catch{this.inode=null;this.pos=0;}this._watch();this._readNew().catch(()=>{});}
|
|
@@ -208,7 +219,18 @@ class FileTail{
|
|
|
208
219
|
async _readNew(){try{const st=fs.statSync(this.filePath);if(st.size<this.pos)this.pos=0;if(st.size===this.pos)return;const stream=fs.createReadStream(this.filePath,{start:this.pos,end:st.size-1,encoding:'utf8'});for await(const chunk of stream){this.buf+=chunk;let idx;while((idx=this.buf.indexOf('\n'))>=0){const line=this.buf.slice(0,idx);this.buf=this.buf.slice(idx+1);if(line.trim())this.onLine(line);}}this.pos=st.size;}catch{}}
|
|
209
220
|
close(){try{this.watch?.close();}catch{}}
|
|
210
221
|
}
|
|
211
|
-
|
|
222
|
+
|
|
223
|
+
const tail=new FileTail(LOG_PATH,line=>{
|
|
224
|
+
try{
|
|
225
|
+
const m=line.match(BAN_RE);
|
|
226
|
+
if(!m) return;
|
|
227
|
+
const ip = m[1];
|
|
228
|
+
if(!ip) return;
|
|
229
|
+
q.push(ip);
|
|
230
|
+
}catch(e){
|
|
231
|
+
log('onLine handler error',e.message||e);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
212
234
|
|
|
213
235
|
function shutdown(){log('Shutting down Fail2Scan...');tail.close();const start=Date.now();const wait=()=>{if(q.running===0||Date.now()-start>10000)process.exit(0);setTimeout(wait,500);};wait();}
|
|
214
236
|
process.on('SIGINT',shutdown);
|