#include <string.h>
#include "../irc/irc.h"
#include "../lib/irc_string.h"
+#include "../lib/version.h"
+#include "../channel/channel.h"
+#include "../localuser/localuserchannel.h"
+#include "../core/nsmalloc.h"
+#include "../lib/irc_ipv6.h"
+
+MODULE_VERSION("")
#define SCANTIMEOUT 60
int rescaninterval;
int warningsent;
int glinedhosts;
-time_t starttime;
+time_t ps_starttime;
+int ps_cache_ext;
+int ps_extscan_ext;
int numscans; /* number of scan types currently valid */
scantype thescans[PSCAN_MAXSCANS];
unsigned int ps_mailport;
sstring *ps_mailname;
+unsigned long scanspermin;
+unsigned long tempscanspermin=0;
+unsigned long lastscants=0;
+
+unsigned int ps_start_ts=0;
+
nick *proxyscannick;
FILE *ps_logfile;
sstring *cfgstr;
int ipbits[4];
+ ps_start_ts = time(NULL);
+
+ ps_cache_ext = registernodeext("proxyscancache");
+ if( ps_cache_ext == -1 ) {
+ Error("proxyscan",ERR_INFO,"failed to reg node ext");
+ return;
+ }
+ ps_extscan_ext = registernodeext("proxyscanextscan");
+ if ( ps_extscan_ext == -1) {
+ Error("proxyscan",ERR_INFO,"failed to reg node ext");
+ return;
+ }
+
memset(scantable,0,sizeof(scantable));
maxscans=200;
activescans=0;
queuedhosts=0;
scansdone=0;
warningsent=0;
- starttime=time(NULL);
+ ps_starttime=time(NULL);
glinedhosts=0;
+ scanspermin=0;
+ lastscants=time(NULL);
+
/* Listen port */
cfgstr=getcopyconfigitem("proxyscan","port","9999",6);
listenport=strtol(cfgstr->content,NULL,10);
freesstring(cfgstr);
ps_mailname=getcopyconfigitem("proxyscan","mailname","some.mail.server",HOSTLEN);
- Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPtostr(ps_mailip),ps_mailname->content);
+ Error("proxyscan",ERR_INFO,"Proxyscan mailer enabled; mailing to %s as %s.",IPlongtostr(ps_mailip),ps_mailname->content);
} else {
ps_mailport=0;
ps_mailname=NULL;
/* Read in the clean hosts */
loadcachehosts();
+ /* Read in any custom ports to scan */
+ loadextrascans();
+
/* Set up the database */
if ((proxyscandbinit())!=0) {
brokendb=1;
proxyscan_addscantype(STYPE_HTTP, 808);
proxyscan_addscantype(STYPE_HTTP, 3332);
proxyscan_addscantype(STYPE_HTTP, 2282);
+ proxyscan_addscantype(STYPE_SOCKS4, 559);
proxyscan_addscantype(STYPE_SOCKS4, 1080);
proxyscan_addscantype(STYPE_SOCKS5, 1080);
proxyscan_addscantype(STYPE_SOCKS4, 1075);
proxyscan_addscantype(STYPE_SOCKS5, 2280);
proxyscan_addscantype(STYPE_SOCKS4, 1180);
proxyscan_addscantype(STYPE_SOCKS5, 1180);
+ proxyscan_addscantype(STYPE_SOCKS4, 9999);
+ proxyscan_addscantype(STYPE_SOCKS5, 9999);
proxyscan_addscantype(STYPE_WINGATE, 23);
proxyscan_addscantype(STYPE_CISCO, 23);
proxyscan_addscantype(STYPE_WINGATE, 1181);
proxyscan_addscantype(STYPE_HTTP, 65506);
proxyscan_addscantype(STYPE_HTTP, 63809);
proxyscan_addscantype(STYPE_HTTP, 63000);
- proxyscan_addscantype(STYPE_SOCKS4, 559);
+ proxyscan_addscantype(STYPE_SOCKS4, 29992);
/* Schedule saves */
schedulerecurring(time(NULL)+3600,0,3600,&dumpcachehosts,NULL);
void registerproxyscannick(void *arg) {
sstring *psnick,*psuser,*pshost,*psrealname;
/* Set up our nick on the network */
+ channel *cp;
psnick=getcopyconfigitem("proxyscan","nick","P",NICKLEN);
psuser=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN);
freesstring(psuser);
freesstring(pshost);
freesstring(psrealname);
+
+ cp=findchannel("#twilightzone");
+ if (!cp) {
+ localcreatechannel(proxyscannick,"#twilightzone");
+ } else {
+ localjoinchannel(proxyscannick,cp);
+ localgetops(proxyscannick,cp);
+ }
}
void _fini(void) {
deregisterlocaluser(proxyscannick,NULL);
+
+ releasenodeext(ps_cache_ext);
+ releasenodeext(ps_extscan_ext);
deregisterhook(HOOK_NICK_NEWNICK,&proxyscan_newnick);
dumpcachehosts(NULL);
/* free() all our structures */
- sfreeall();
+ nsfreeall(POOL_PROXYSCAN);
freesstring(ps_mailname);
#if defined(PROXYSCAN_MAIL)
nick *sender;
char *msg;
int i;
+ struct irc_in_addr sin;
+ unsigned char bits;
+ patricia_node_t *node;
switch(message) {
case LU_KILLED:
if (!ircd_strncmp(msg,"debug",5)) {
proxyscandebug(sender);
}
-
- if (!ircd_strncmp(msg,"scan ",5)) {
+
+ if (!ircd_strncmp(msg,"spew ",5)) {
+ /* check our database for the ip supplied */
unsigned long a,b,c,d;
if (4 != sscanf(&msg[5],"%lu.%lu.%lu.%lu",&a,&b,&c,&d)) {
- sendnoticetouser(proxyscannick,sender,"Usage: scan a.b.c.d");
+ sendnoticetouser(proxyscannick,sender,"Usage: spew x.x.x.x");
} else {
- sendnoticetouser(proxyscannick,sender,"Forcing scan of %lu.%lu.%lu.%lu",a,b,c,d);
- /* Just queue the scans directly here.. plonk them on the priority queue */
- for(i=0;i<numscans;i++) {
- queuescan((a<<24)+(b<<16)+(c<<8)+d,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
+ /* check db */
+ proxyscanspewip(proxyscannick,sender,a,b,c,d);
+ }
+ }
+
+ if (!ircd_strncmp(msg,"showkill ",9)) {
+ /* check our database for the id supplied */
+ unsigned long a;
+ if (1 != sscanf(&msg[9],"%lu",&a)) {
+ sendnoticetouser(proxyscannick,sender,"Usage: showkill <id>");
+ } else {
+ /* check db */
+ proxyscanshowkill(proxyscannick,sender,a);
+ }
+ }
+
+ if (!ircd_strncmp(msg,"scan ",5)) {
+ if (0 == ipmask_parse(&msg[5],&sin, &bits)) {
+ sendnoticetouser(proxyscannick,sender,"Usage: scan <ip>");
+ } else {
+ sendnoticetouser(proxyscannick,sender,"Forcing scan of %s",IPtostr(sin));
+ // * Just queue the scans directly here.. plonk them on the priority queue * /
+ node = refnode(iptree, &sin, bits); /* node leaks node here - should only allow to scan a nick? */
+ for(i=0;i<numscans;i++) {
+ queuescan(node,thescans[i].type,thescans[i].port,SCLASS_NORMAL,time(NULL));
}
}
}
}
}
- if (!ircd_strncmp(msg,"help",4)) {
+ if ((!ircd_strncmp(msg,"help",4)) || (!ircd_strncmp(msg,"showcommands",12))) {
sendnoticetouser(proxyscannick,sender,"Proxyscan commands:");
- sendnoticetouser(proxyscannick,sender,"-------------------------------------------");
- sendnoticetouser(proxyscannick,sender,"help Shows this help");
- sendnoticetouser(proxyscannick,sender,"status Prints status information");
- sendnoticetouser(proxyscannick,sender,"listopen Shows open proxies found recently");
- sendnoticetouser(proxyscannick,sender,"save Saves the clean host database");
+ sendnoticetouser(proxyscannick,sender,"----------------------------------------------------------------------");
+ sendnoticetouser(proxyscannick,sender,"help Shows this help");
+ sendnoticetouser(proxyscannick,sender,"status Prints status information");
+ sendnoticetouser(proxyscannick,sender,"listopen Shows open proxies found recently");
+ sendnoticetouser(proxyscannick,sender,"save Saves the clean host database");
+ sendnoticetouser(proxyscannick,sender,"scan <ip> Force scan of the supplied IP");
+ sendnoticetouser(proxyscannick,sender,"spew <ip> Find <ip> in our list of open proxies");
+ sendnoticetouser(proxyscannick,sender,"showkill <id> Shows details of a kill or gline made by the service");
}
}
return NULL;
}
-void startscan(unsigned int IP, int type, int port, int class) {
+void startscan(patricia_node_t *node, int type, int port, int class) {
scan *sp;
+ float scantmp;
+
+ if (scansdone>maxscans)
+ {
+ /* ignore the first maxscans as this will skew our scans per second! */
+ tempscanspermin++;
+ if ((lastscants+60) <= time(NULL))
+ {
+ /* ok, at least 60 seconds has passed, calculate the scans per minute figure */
+ scantmp = time(NULL) - lastscants;
+ scantmp = tempscanspermin / scantmp;
+ scantmp = (scantmp * 60);
+ scanspermin = scantmp;
+ lastscants = time(NULL);
+ tempscanspermin = 0;
+ }
+ }
sp=getscan();
sp->outcome=SOUTCOME_INPROGRESS;
sp->port=port;
- sp->IP=IP;
+ sp->node=node;
sp->type=type;
sp->class=class;
sp->bytesread=0;
sp->totalbytesread=0;
memset(sp->readbuf, '\0', PSCAN_READBUFSIZE);
- sp->fd=createconnectsocket(sp->IP,sp->port);
+ sp->fd=createconnectsocket(irc_in_addr_v4_to_int(&((patricia_node_t *)sp->node)->prefix->sin),sp->port);
sp->state=SSTATE_CONNECTING;
if (sp->fd<0) {
/* Couldn't set up the socket? */
if (sp->outcome==SOUTCOME_CLOSED &&
((sp->class==SCLASS_CHECK) ||
(sp->class==SCLASS_NORMAL && (sp->state==SSTATE_SENTREQUEST || sp->state==SSTATE_GOTRESPONSE))))
- queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
+ queuescan(sp->node, sp->type, sp->port, SCLASS_PASS2, time(NULL)+300);
if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS2)
- queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
+ queuescan(sp->node, sp->type, sp->port, SCLASS_PASS3, time(NULL)+300);
if (sp->outcome==SOUTCOME_CLOSED && sp->class==SCLASS_PASS3)
- queuescan(sp->IP, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
+ queuescan(sp->node, sp->type, sp->port, SCLASS_PASS4, time(NULL)+300);
if (sp->outcome==SOUTCOME_OPEN) {
hitsbyclass[sp->class]++;
/* Lets try and get the cache record. If there isn't one, make a new one. */
- if (!(chp=findcachehost(sp->IP)))
- chp=addcleanhost(sp->IP, time(NULL));
-
+ if (!(chp=findcachehost(sp->node))) {
+ chp=addcleanhost(time(NULL));
+ patricia_ref_prefix(sp->node->prefix);
+ sp->node->exts[ps_cache_ext] = chp;
+ }
/* Stick it on the cache's list of proxies, if necessary */
for (fpp=chp->proxies;fpp;fpp=fpp->next)
if (fpp->type==sp->type && fpp->port==sp->port)
if (!chp->glineid) {
glinedhosts++;
- loggline(chp);
+ loggline(chp, sp->node);
irc_send("%s GL * +*@%s 1800 :Open Proxy, see http://www.quakenet.org/openproxies.html - ID: %d",
- mynumeric->content,IPtostr(sp->IP),chp->glineid);
- Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(sp->IP));
+ mynumeric->content,IPtostr(((patricia_node_t *)sp->node)->prefix->sin),chp->glineid);
+ Error("proxyscan",ERR_DEBUG,"Found open proxy on host %s",IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
} else {
- loggline(chp); /* Update log only */
+ loggline(chp, sp->node); /* Update log only */
}
/* Update counter */
for(i=0;i<SCANHASHSIZE;i++) {
for(sp=scantable[i];sp;sp=sp->next) {
/* If there is a pending scan, delete it's clean host record.. */
- if ((chp=findcachehost(sp->IP)) && !chp->proxies)
+ if ((chp=findcachehost(sp->node)) && !chp->proxies) {
+ sp->node->exts[ps_cache_ext] = NULL;
+ derefnode(iptree,sp->node);
delcachehost(chp);
+ }
if (sp->fd!=-1) {
deregisterhandler(sp->fd,1);
int totaldetects=0;
int ord[PSCAN_MAXSCANS];
- sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-starttime, 1));
+ sendnoticetouser(proxyscannick,np,"Service uptime: %s",longtoduration(time(NULL)-ps_starttime, 1));
sendnoticetouser(proxyscannick,np,"Total scans completed: %d",scansdone);
sendnoticetouser(proxyscannick,np,"Total hosts glined: %d",glinedhosts);
+ sendnoticetouser(proxyscannick,np,"pendingscan structures: %lu x %lu bytes = %lu bytes total",countpendingscan,
+ sizeof(pendingscan), (countpendingscan * sizeof(pendingscan)));
+
sendnoticetouser(proxyscannick,np,"Currently active scans: %d/%d",activescans,maxscans);
+ sendnoticetouser(proxyscannick,np,"Processing speed: %lu scans per minute",scanspermin);
sendnoticetouser(proxyscannick,np,"Normal queued scans: %d",normalqueuedscans);
sendnoticetouser(proxyscannick,np,"Timed queued scans: %d",prioqueuedscans);
sendnoticetouser(proxyscannick,np,"'Clean' cached hosts: %d",cleancount());
sendnoticetouser(proxyscannick,np,"'Dirty' cached hosts: %d",dirtycount());
-
+
+ sendnoticetouser(proxyscannick,np,"Extra scans: %d", extrascancount());
for (i=0;i<5;i++)
sendnoticetouser(proxyscannick,np,"Open proxies, class %1d: %d/%d (%.2f%%)",i,hitsbyclass[i],scansbyclass[i],((float)hitsbyclass[i]*100)/scansbyclass[i]);
int activescansfound=0;
int totalscansfound=0;
scan *sp;
+ patricia_node_t *node;
+ cachehost *chp;
sendnoticetouser(proxyscannick,np,"Active scans : %d",activescans);
}
totalscansfound++;
sendnoticetouser(proxyscannick,np,"fd: %d type: %d port: %d state: %d outcome: %d IP: %s",
- sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(sp->IP));
+ sp->fd,sp->type,sp->port,sp->state,sp->outcome,IPtostr(((patricia_node_t *)sp->node)->prefix->sin));
}
}
+ PATRICIA_WALK (iptree->head, node) {
+ if ( node->exts[ps_cache_ext] ) {
+ chp = (cachehost *) node->exts[ps_cache_ext];
+ if (chp)
+ sendnoticetouser(proxyscannick,np,"node: %s , chp: %d", IPtostr(((patricia_node_t *)node)->prefix->sin), chp);
+ }
+ } PATRICIA_WALK_END;
+
sendnoticetouser(proxyscannick,np,"Total %d scans actually found (%d active)",totalscansfound,activescansfound);
}