diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-01-13 13:01:05 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-01-13 13:01:05 -0800 |
commit | 252e55d15a0fbc21f36f45361b61aade61ab3dbf (patch) | |
tree | 846fca1fe7f426d938074103c9c10bb2e89175e1 | |
parent | 86defc1e3911346cb4b1435980c08c319d58f63a (diff) | |
download | txrban-252e55d15a0fbc21f36f45361b61aade61ab3dbf.tar.gz txrban-252e55d15a0fbc21f36f45361b61aade61ab3dbf.tar.bz2 txrban-252e55d15a0fbc21f36f45361b61aade61ab3dbf.zip |
Replace parallel hashes with one hash of client structs.
-rw-r--r-- | txrban.txr | 107 |
1 files changed, 57 insertions, 50 deletions
@@ -1,18 +1,22 @@ @(load "config") @(load "utils") @(do - (cond - (t (daemon nil nil) - (openlog `txrban-@self` log-pid log-authpriv)) - (nil (set *stdlog* *stdout*))) + (defstruct client-info nil + (ip nil) + (access-hist nil) + (points 0) + (banned nil) + (extrainfo nil)) - (defvar *access-hist* (hash :equal-based)) - (defvar *points* (hash :equal-based)) - (defvar *banned* (hash :equal-based)) - (defvar *extrainfo* (hash :equal-based)) + (defvarl client-hash (hash :equal-based)) (defvar *off* "") ;; set this to "#" to comment out commands + (defun get-client-info (ip) + (hash-update-1 client-hash ip [iff have + identity + (ret (new client-info ip ip))] nil)) + ;;; Report activity of an ip address, for a given time ;;; Levels are 0 through 5. 0 is normal access: client isn't ;;; doing anything wrong, but should be monitored for excessive activity. @@ -20,69 +24,72 @@ ;;; 5 points lead to a ban, whose severity depends on how many ;;; points in excess of 5 there are. (defun report (ip time level : extrainfo) - (push time [*access-hist* ip]) - (if (and extrainfo (not (memqual extrainfo [*extrainfo* ip]))) - (push extrainfo [*extrainfo* ip])) - (if (> level 0) - (let* ((points (inc [*points* ip 0] level)) - (severity (- points 5))) - (if (>= severity 0) - (progn - (del [*points* ip]) - (ban ip time (ban-duration severity)))))) + (let ((cli (get-client-info ip))) + (push time cli.access-hist) + (when extrainfo + (pushnew extrainfo cli.extrainfo)) + + (if (> level 0) + (let* ((points (inc cli.points level)) + (severity (- points 5))) + (if (>= severity 0) + (progn + (set cli.points 0) + (ban cli time (ban-duration severity)))))) (process-histories time) - (do-expiry time)) + (do-expiry time))) (defun get-info (ip) - [*extrainfo* ip]) + (iflet ((cli [client-hash ip])) + cli.extrainfo)) (defun clear (ip) - (del [*access-hist* ip]) - (del [*extrainfo* ip]) - (del [*points* ip]) - (unban ip)) + (del [client-hash ip])) (defun ban-duration (severity) [*ban-duration* (min (- (length *ban-duration*) 1) severity)]) - (defun ban (ip time howlong) - (let* ((banned [*banned* ip]) - (until (car banned)) + (defun ban (cli time howlong) + (let* ((until (if cli.banned (to cli.banned))) (new-until (+ time howlong))) (cond - ((not banned) - (sh `@{*off*}iptables -I INPUT 1 -s @ip -i @{*iface*} -j DROP`) - (debug "banned ~a for ~a starting on ~a\n" ip + ((not cli.banned) + (sh `@{*off*}iptables -I INPUT 1 -s @{cli.ip} -i @{*iface*} -j DROP`) + (debug "banned ~a for ~a starting on ~a\n" cli.ip (hrtime howlong) (time-string-local time "%c")) - (set [*banned* ip] ^(,new-until ,*time))) + (set cli.banned (rcons time new-until))) ((> new-until until) - (debug "extending ban on ~a for ~a starting on ~a\n" ip - (hrtime howlong) (time-string-local time "%c")) - (set [*banned* ip] ^(,new-until ,*time)))))) + (debug "extending ban on ~a for ~a starting on ~a\n" cli.ip + (hrtime howlong) (time-string-local time "%c")) + (set cli.banned (rcons time new-until)))))) (defun process-histories (time) (let ((long-range (- time *long-period*)) (short-range (- time *short-period*))) - (dohash (ip acc *access-hist*) - (let* ((nacc (remove-if (op < @1 long-range) acc)) + (dohash (ip cli client-hash) + (let* ((nacc (remove-if (op < @1 long-range) cli.access-hist)) (long-count (length nacc)) (short-count (count-if (op >= @1 short-range) nacc))) (if nacc - (set [*access-hist* ip] nacc) + (set cli.access-hist nacc) (progn - (del [*access-hist* ip]) - (del [*extrainfo* ip]))) - (if (> long-count *long-limit*) - (ban ip time *long-ban*)) - (if (> short-count *short-limit*) - (ban ip time *short-ban*)))))) + (set cli.access-hist nil) + (set cli.extrainfo nil))) + (cond + ((> long-count *long-limit*) (ban cli time *long-ban*)) + ((> short-count *short-limit*) (ban cli time *short-ban*))))))) (defun do-expiry (now-time) - (dohash (ip timeinfo *banned*) - (if (<= (car timeinfo) now-time) - (unban ip)))) + (dohash (ip cli client-hash) + (if (and cli.banned (<= (to cli.banned) now-time)) + (unban cli)))) + + (defun unban (cli) + (sh `@{*off*}iptables -D INPUT -s @{cli.ip} -i @{*iface*} -j DROP`) + (debug "unbanned ~a\n" cli.ip) + (set cli.banned nil)) - (defun unban (ip) - (sh `@{*off*}iptables -D INPUT -s @ip -i @{*iface*} -j DROP`) - (debug "unbanned ~a\n" ip) - (del [*banned* ip]))) + (cond + (t (daemon nil nil) + (openlog `txrban-@self` log-pid log-authpriv)) + (nil (set *stdlog* *stdout*)))) |