Check incoming connections with AbuseIPDB

This section contains scripts that hMailServer has contributed with. hMailServer 5 is needed to use these.
Post Reply
Po-In
New user
New user
Posts: 4
Joined: 2018-05-14 14:46

Check incoming connections with AbuseIPDB

Post by Po-In » 2018-05-14 15:09

Hi all,

I use the website www.AbuseIPDB.com quite a lot for looking up malicious IP addresses.
I've also created some code that will query the AbuseIPDB API and evaluate the response to reject the connection if reported more than 10 times in the last 30 days.
Please note that you need register at AbuseIPDB to obtain an API key.
Use at your own discretion...

Good luck!

EDIT: UPDATED WORKING VERSION FOLLOWS IN THE SECOND POST. (mod.)


Code: Select all

Sub OnClientConnect(oClient)
'Variables
   ClientIp       = oClient.IpAddress                 'Connecting remote IP address
   ClientPort     = oClient.Port                      'Port it is connecting to
   DetectPort     = 25                                'Variable port to check
   LocalHost      = "127.0.0.1"                       'Variable for LocalHost IP address
   APIkey         = "GetYourOwn"                      'API key (get your own at AbuseIPDB.Com)
   APIDays        = 30                                'Variable AbuseIPDB history in days
   APICount       = 10                                'Variable threshold to use for rejecting connections
   
'Check IP Address with AbuseIPDB API
   If ClientPort = DetectPort and ClientIp <> LocalHost Then
      Set objXMLHTTP = CreateObject("msxml2.xmlhttp.6.0")
      objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & ClientIp & "/json", False
      objXMLHTTP.setRequestHeader "Content-Type", "application/json"
      objXMLHTTP.Send "key=" & APIKey & "&days=" & APIDays
      ResponseText = objXMLHTTP.responseText

'Evaluate response (quick & dirty JSON 'parsing')
      If ResponseText <> "[]" and InStr(Replace(ResponseText, chr(34),""),"isWhitelisted:true") = 0 then
         RecordCount = CountString(ResponseText, ClientIp)
'Reject connection and write eventlog
         If RecordCount > APICount Then
            Result.Value = 1
            EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected (reported " & RecordCount & " times)")
'Accept connection and write warning in eventlog
         Else
            Result.Value = 0
            EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " warning  (reported " & RecordCount & " times)")
         End If
      End If
'Accept connection because IP address is reported but whitelisted at AbuseIPDB
      If ResponseText <> "[]" and InStr(Replace(ResponseText, chr(34),""),"isWhitelisted:true") <> 0 then
         Result.Value = 0
         RecordCount = CountString(ResponseText, ClientIp)
         EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " whitelisted (reported " & RecordCount & " times)")
      End If
      Set objXMLHTTP = Nothing
   End If
End Sub

Public Function CountString(VariableString, SearchString)
   CountString = 0
      For x = 1 to len(VariableString) - len(SearchString)
         If Mid(VariableString,x,len(SearchString)) = SearchString then
            CountString = CountString +1
         End If
      Next
End Function

Po-In
New user
New user
Posts: 4
Joined: 2018-05-14 14:46

Re: Check incoming connections with AbuseIPDB

Post by Po-In » 2018-05-16 10:13

Version 2: :roll:

Code: Select all

Sub OnClientConnect(oClient)
'Variables
   ClientIp       = oClient.IpAddress                 'Connecting remote IP address
   ClientPort     = oClient.Port                      'Port it is connecting to
   DetectPort     = 25                                'Variable port to check
   LocalHost      = "127.0.0.1"                       'Variable for LocalHost IP address
   APIkey         = "GetYourOwn"                      'API key (get your own at AbuseIPDB.Com)
   APIDays        = 30                                'Variable AbuseIPDB history in days
   APICount       = 10                                'Variable threshold to use for rejecting connections
   
'Check IP Address with AbuseIPDB API
   If ClientPort = DetectPort and ClientIp <> LocalHost Then
      Set objXMLHTTP = CreateObject("msxml2.xmlhttp.6.0")
      objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & ClientIp & "/json?key=" & APIKey & "&days=" &APIDays, False
      objXMLHTTP.Send ""
      ResponseText = objXMLHTTP.responseText

'Evaluate response (quick & dirty JSON 'parsing')
      If ResponseText <> "[]" and InStr(Replace(ResponseText, chr(34),""),"isWhitelisted:true") = 0 then
         RecordCount = CountString(ResponseText, ClientIp)
'Reject connection and write eventlog
         If RecordCount > APICount Then
            Result.Value = 1
            EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected (reported " & RecordCount & " times)")
'Accept connection and write warning in eventlog
         Else
            Result.Value = 0
            EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " warning  (reported " & RecordCount & " times)")
         End If
      End If
'Accept connection because IP address is reported but whitelisted at AbuseIPDB
      If ResponseText <> "[]" and InStr(Replace(ResponseText, chr(34),""),"isWhitelisted:true") <> 0 then
         Result.Value = 0
         RecordCount = CountString(ResponseText, ClientIp)
         EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " whitelisted (reported " & RecordCount & " times)")
      End If
      Set objXMLHTTP = Nothing
   End If
End Sub

Public Function CountString(VariableString, SearchString)
   CountString = 0
   For x = 1 to len(VariableString) - len(SearchString)
      If Mid(VariableString,x,len(SearchString)) = SearchString then
         CountString = CountString +1
      End If
   Next
End Function

User avatar
jimimaseye
Moderator
Moderator
Posts: 8171
Joined: 2011-09-08 17:48

Re: Check incoming connections with AbuseIPDB

Post by jimimaseye » 2018-05-17 09:03

If it does what you say it does and it is effective (I havent tried it) then it looks good. Thanks for posting.
HMS 5.6.6 B2383 on Win Server 2008 R2 Foundation, + 5.6.7-B2415 on test.
SpamassassinForWindows 3.4.0 spamd service
AV: Clamwin + Clamd service + sanesecurity defs : https://www.hmailserver.com/forum/viewtopic.php?f=21&t=26829

Po-In
New user
New user
Posts: 4
Joined: 2018-05-14 14:46

Re: Check incoming connections with AbuseIPDB

Post by Po-In » 2018-05-24 09:45

I wish I could keep editting or delete the original post(s), because the code is evolving :)

User avatar
jimimaseye
Moderator
Moderator
Posts: 8171
Joined: 2011-09-08 17:48

Re: Check incoming connections with AbuseIPDB

Post by jimimaseye » 2018-05-24 10:08

Post your updates - I or mod Mattg can edit the thread and remove old posts/code if you want. Just make it clear about what is what.
HMS 5.6.6 B2383 on Win Server 2008 R2 Foundation, + 5.6.7-B2415 on test.
SpamassassinForWindows 3.4.0 spamd service
AV: Clamwin + Clamd service + sanesecurity defs : https://www.hmailserver.com/forum/viewtopic.php?f=21&t=26829

Po-In
New user
New user
Posts: 4
Joined: 2018-05-14 14:46

UPDATE: Check incoming connections with AbuseIPDB

Post by Po-In » 2018-05-24 13:46

Here's one that doesn't need registration (even though I think you should register anyway and show some support to AbuseIPDB).

The function 'CheckAbuseIPDBConfidence' returns the 'Confidence of Abuse' percentage for the given IP address, as calculated by AbuseIPDB.
It parses the page data until it finds the section that represents the value. This will work as long as AbuseIPDB doesn't change the design :)

As shown below, I refuse connections from IP addresses that score higher than 40%, which works pretty well for me.
About 75% of the connecting IP addresses score 40 or above, so it helps a lot.

Code: Select all

Sub OnClientConnect(oClient)
'Variables
	ClientIp				= oClient.IpAddress			'Connecting remote IP address
	WhiteList				= "#127.0.0.1#a.b.c.d#1.2.3.4#"		'Variable array for whitelisted IP addresses to exclude, localhost, maybe your servers IP address, your WebClient IP address whatever
	Percentage 				= "0"					'Default value

'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage			= CheckAbuseIPDBConfidence(ClientIP)

'Process reported percentage		
		If Percentage > 40 then
			Result.Value 		= 1
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected: Confidence of Abuse: " & Percentage & "%.")
		ElseIf Percentage > 10 then
			Result.Value 		= 0
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " warning: Confidence of Abuse: " & Percentage & "%.")
		ElseIf Percentage > 0 then
			Result.Value 		= 0
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " notification: Confidence of Abuse: " & Percentage & "%.")
		End If
	End If
End Sub

Public Function CheckAbuseIPDBConfidence(IPAddress)
	CheckAbuseIPDBConfidence		= "0"
	Set objXMLHTTP				= CreateObject("msxml2.xmlhttp.6.0")
		objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & IPAddress, False
		objXMLHTTP.Send ""
		ResponseText			= objXMLHTTP.responseText
		ResponseArray			= Split(ResponseText, VbLf)
		For Each ResponseLine in ResponseArray
			If Left(ResponseLine, 6) = "<span>" And Right(ResponseLine, 8) = "%</span>" Then
				CheckAbuseIPDBConfidence 	= Mid(ResponseLine,7, Len(ResponseLine)-14)
				Exit For
			End If
		Next	
	Set objXMLHTTP 				= Nothing
End Function	


insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-26 16:28

I'm actually surprised that this script has not seen more interest. With something like this combined to an autoban or even better, firewall ban inclusion, some wonderful things could happen.

For example:

Using Sorren's AutoBan logic and Cports, you would reject, ban the ip address, and forcefully close the connection. Never to hear from them again:

Code: Select all

Sub OnClientConnect(oClient)
'Variables
	ClientIp				= oClient.IpAddress			'Connecting remote IP address
	WhiteList				= "#127.0.0.1#A.B.C.D#1.2.3.4#"		'Variable array for whitelisted IP addresses to exclude, localhost, maybe your servers IP address, your WebClient IP address whatever
	Percentage 				= "0"					'Default value
'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage			= CheckAbuseIPDBConfidence(ClientIP)
'Process reported percentage		
		If Percentage > 40 then
			Result.Value 		= 1
			Call AutoBan(oClient.IPAddress, "IP Address Spamlisted", 2, "d")
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected: Confidence of Abuse: " & Percentage & "%.")
		ElseIf Percentage > 10 then
			Result.Value 		= 0
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " warning: Confidence of Abuse: " & Percentage & "%.")
		ElseIf Percentage > 0 then
			Result.Value 		= 0
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " notification: Confidence of Abuse: " & Percentage & "%.")
		End If
	End If
End Sub
	
	
	Sub AutoBan(sIPAddress, sReason, iDuration, sType)
'
'     sType can be one of the following;
'
'     "yyyy" Year, "m" Month, "d" Day, "h" Hour, "n" Minute, "s" Second
'
'     Cports can be obtained here -> http://www.nirsoft.net/utils/cports.html
'
  Dim oApp : Set oApp = CreateObject("hMailServer.Application")
  Call oApp.Authenticate("*****", "*******")
  With LockFile("c:\hmailserver\temp\autoban.lck")
	 On Error Resume Next
	 oApp.Settings.SecurityRanges.Refresh
	 If (oApp.Settings.SecurityRanges.ItemByName("(" & sReason & ") " & sIPAddress) Is Nothing) Then
		With oApp.Settings.SecurityRanges.Add
		   .Name = "(" & sReason & ") " & IPAddress
		   .LowerIP = sIPAddress
		   .UpperIP = sIPAddress
		   .Priority = 20
		   .Expires = True
		   .ExpiresTime = DateAdd(sType, iDuration, Now())
		   .Save
		End With
	 End If
	 oApp.Settings.SecurityRanges.Refresh
	 On Error Goto 0
	 .Close
  End With
  With CreateObject("WScript.Shell")
	 .Run "CPorts /close * * " & sIPAddress & " *", 0, True
  End With
End Sub
I'm testing it now. Seems to be pretty effective:

Code: Select all

3892	"2018-08-26 07:16:15.898"	"AbuseIPDB: IP Address 103.207.39.104 rejected: Confidence of Abuse: 50%."
3696	"2018-08-26 07:16:17.083"	"AbuseIPDB: IP Address 103.207.39.104 rejected: Confidence of Abuse: 50%."
3844	"2018-08-26 07:16:17.083"	"AbuseIPDB: IP Address 103.207.39.104 rejected: Confidence of Abuse: 50%."
3740	"2018-08-26 07:16:17.995"	"AbuseIPDB: IP Address 103.207.39.104 rejected: Confidence of Abuse: 50%."
3848	"2018-08-26 07:16:17.995"	"AbuseIPDB: IP Address 103.207.39.104 rejected: Confidence of Abuse: 50%."
3828	"2018-08-26 07:17:52.496"	"AbuseIPDB: IP Address 113.190.213.119 notification: Confidence of Abuse: 6%."
3768	"2018-08-26 07:17:52.496"	"AbuseIPDB: IP Address 107.158.203.61 notification: Confidence of Abuse: 5%."
3688	"2018-08-26 07:19:47.023"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."
3816	"2018-08-26 07:19:47.023"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."
3760	"2018-08-26 07:20:09.296"	"AbuseIPDB: IP Address 104.254.212.65 warning: Confidence of Abuse: 14%."
3740	"2018-08-26 07:20:10.185"	"AbuseIPDB: IP Address 107.158.203.61 notification: Confidence of Abuse: 5%."
3828	"2018-08-26 07:22:36.930"	"AbuseIPDB: IP Address 45.225.4.91 warning: Confidence of Abuse: 39%."
3688	"2018-08-26 07:22:37.301"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."
3848	"2018-08-26 07:22:38.388"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."
3816	"2018-08-26 07:23:19.955"	"AbuseIPDB: IP Address 182.75.206.218 notification: Confidence of Abuse: 3%."
3740	"2018-08-26 07:23:45.691"	"AbuseIPDB: IP Address 168.205.38.100 warning: Confidence of Abuse: 11%."
3696	"2018-08-26 07:25:28.365"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."
3768	"2018-08-26 07:25:29.198"	"AbuseIPDB: IP Address 203.55.21.251 notification: Confidence of Abuse: 9%."
3816	"2018-08-26 07:25:29.198"	"AbuseIPDB: IP Address 95.31.2.199 notification: Confidence of Abuse: 7%."
3928	"2018-08-26 07:25:50.028"	"AbuseIPDB: IP Address 104.129.21.184 notification: Confidence of Abuse: 5%."

Thank you for your contribution.

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-08-27 17:54

Site is using TLS 1.2 so they are ruling out anything older than Windows Server 2008 R2 and you still need to manually enable TLS 1.2 on 2008 R2 for scripting.
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-28 17:27

I have banned near 3000 ip addresses in 24 hours using this. I am doing spot lookups on these IP addresses and so far, they are definitely IP addresses that need to be banned!

Hey SorenR,

I take it that you are on an older OS. Have you had any issues using cports to close connections? I cant seem to get it to work with 2016 server. Granted I have not put much debug time into it, but i was forced to change your logic from this:

Code: Select all

  With CreateObject("WScript.Shell")
	 .Run "CPorts /close * * " & sIPAddress & " *", 0, True
  End With
To this:

Code: Select all

	Set objShell2 = CreateObject("WScript.Shell")
	objShell2.Run "CPorts /close * * " & sIPAddress & " *", 0, True
	objShell2.Close
While i no longer get null errors, I don't particularly see it working either. I may have to figure out how to output some feedback to figure it out.

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-08-28 18:21

Yeah, I'm on Server 2003 R2 :roll:

Your change in logic should not change anything, I have no idea why you get different results.

Perhaps you could try ...

Code: Select all

With CreateObject("WScript.Shell")
   .Run "runas /savecred /user:administrator CPorts /close * * " & sIPAddress & " *", 0, True
End With
I don't know if it works but it's a thought ;-)

Re. banning servers. I only ban servers from my IDS routine, SPAM, snowshoe and other detections I only deny access when contacted. It's faster this way when you reach 500+ banned servers.
insomniac2k2 wrote:
2018-08-28 17:27
I have banned near 3000 ip addresses in 24 hours using this. I am doing spot lookups on these IP addresses and so far, they are definitely IP addresses that need to be banned!

Hey SorenR,

I take it that you are on an older OS. Have you had any issues using cports to close connections? I cant seem to get it to work with 2016 server. Granted I have not put much debug time into it, but i was forced to change your logic from this:

Code: Select all

  With CreateObject("WScript.Shell")
	 .Run "CPorts /close * * " & sIPAddress & " *", 0, True
  End With
To this:

Code: Select all

	Set objShell2 = CreateObject("WScript.Shell")
	objShell2.Run "CPorts /close * * " & sIPAddress & " *", 0, True
	objShell2.Close
While i no longer get null errors, I don't particularly see it working either. I may have to figure out how to output some feedback to figure it out.
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-28 18:54

I'll give that a try. Running as admin makes sense.

I've been worried about the ban list getting a little heavy but have not seen performance issues yet. My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would become moot.

Thanks for the idea. I'll give it a try now.
SorenR wrote:
2018-08-28 18:21
Yeah, I'm on Server 2003 R2 :roll:

Your change in logic should not change anything, I have no idea why you get different results.

Perhaps you could try ...

Code: Select all

With CreateObject("WScript.Shell")
   .Run "runas /savecred /user:administrator CPorts /close * * " & sIPAddress & " *", 0, True
End With
I don't know if it works but it's a thought ;-)

Re. banning servers. I only ban servers from my IDS routine, SPAM, snowshoe and other detections I only deny access when contacted. It's faster this way when you reach 500+ banned servers.
insomniac2k2 wrote:
2018-08-28 17:27
I have banned near 3000 ip addresses in 24 hours using this. I am doing spot lookups on these IP addresses and so far, they are definitely IP addresses that need to be banned!

Hey SorenR,

I take it that you are on an older OS. Have you had any issues using cports to close connections? I cant seem to get it to work with 2016 server. Granted I have not put much debug time into it, but i was forced to change your logic from this:

Code: Select all

  With CreateObject("WScript.Shell")
	 .Run "CPorts /close * * " & sIPAddress & " *", 0, True
  End With
To this:

Code: Select all

	Set objShell2 = CreateObject("WScript.Shell")
	objShell2.Run "CPorts /close * * " & sIPAddress & " *", 0, True
	objShell2.Close
While i no longer get null errors, I don't particularly see it working either. I may have to figure out how to output some feedback to figure it out.

User avatar
RvdH
Senior user
Senior user
Posts: 817
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Check incoming connections with AbuseIPDB

Post by RvdH » 2018-08-28 22:34

insomniac2k2 wrote:
2018-08-28 18:54
My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would
Well, how big a issue is that actually? The connection will time-out sooner or later... is it really necessary to forcefully close an auto-banned ipaddress ?
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-28 22:39

It's been a real issue several times in the recent past. Even after modifying the allowed amount of threads on the server, I have had hmail stop passing emails due to every thread being used/reserved. Once forcefully releasing these sessions, mail resumes immediately.

I should note that I have very heavy volume servers, so i'm sure that this would not be an issue for most people.
RvdH wrote:
2018-08-28 22:34
insomniac2k2 wrote:
2018-08-28 18:54
My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would
Well, how big a issue is that actually? The connection will time-out sooner or later... is it really necessary to forcefully close an auto-banned ipaddress ?

User avatar
RvdH
Senior user
Senior user
Posts: 817
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Check incoming connections with AbuseIPDB

Post by RvdH » 2018-08-28 22:42

I can hardly believe that....what are we talking about here? Thousands and thousands of simultaneous connections and all being auto-banned?

You are aware this Cports is only triggered when an ipaddress is auto-banned, not whenever it tries to connect later on
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-08-28 22:56

RvdH wrote:
2018-08-28 22:34
insomniac2k2 wrote:
2018-08-28 18:54
My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would
Well, how big a issue is that actually? The connection will time-out sooner or later... is it really necessary to forcefully close an auto-banned ipaddress ?
I use it primarely for my IDS code to kick the server completely, otherwise it will remain connected and continue to "talk". I've seen servers open 5-6 sessions simultaneously which results in my code trying to re-ban the same server multiple times. With CPort killing all sessions with the same IP Address, that problem goes away.
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

User avatar
RvdH
Senior user
Senior user
Posts: 817
Joined: 2008-06-27 14:42
Location: Netherlands

Re: Check incoming connections with AbuseIPDB

Post by RvdH » 2018-08-28 23:47

In that case... 10kb :wink:
Source: stackoverflow.com

Code: Select all

using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace ConnectionManager
{
    class Disconnector
    {
    }

    public class Starter
    {
        public static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Disconnect IP1 [IP2 [IP3 [IPn]]]");
                Console.WriteLine("");
                Console.WriteLine("Connections up now:");
                string[] cons = Disconnecter.Connections(Disconnecter.State.Established);
                foreach (string s in cons)
                {
                    Console.WriteLine(s);
                }
            }
            else
            {
                foreach (string s in args)
                {
                    Disconnecter.CloseRemoteIP(s);
                }
            }
#if DEBUG
            Console.ReadKey();
#endif
        }
    }

    public class Disconnecter
    {

        /// <summary> 
        /// Enumeration of the states 
        /// </summary> 
        public enum State
        {
            /// <summary> All </summary> 
            All = 0,
            /// <summary> Closed </summary> 
            Closed = 1,
            /// <summary> Listen </summary> 
            Listen = 2,
            /// <summary> Syn_Sent </summary> 
            Syn_Sent = 3,
            /// <summary> Syn_Rcvd </summary> 
            Syn_Rcvd = 4,
            /// <summary> Established </summary> 
            Established = 5,
            /// <summary> Fin_Wait1 </summary> 
            Fin_Wait1 = 6,
            /// <summary> Fin_Wait2 </summary> 
            Fin_Wait2 = 7,
            /// <summary> Close_Wait </summary> 
            Close_Wait = 8,
            /// <summary> Closing </summary> 
            Closing = 9,
            /// <summary> Last_Ack </summary> 
            Last_Ack = 10,
            /// <summary> Time_Wait </summary> 
            Time_Wait = 11,
            /// <summary> Delete_TCB </summary> 
            Delete_TCB = 12
        }

        /// <summary> 
        /// Connection info 
        /// </summary> 
        private struct MIB_TCPROW
        {
            public int dwState;
            public int dwLocalAddr;
            public int dwLocalPort;
            public int dwRemoteAddr;
            public int dwRemotePort;
        }

        //API to get list of connections 
        [DllImport("iphlpapi.dll")]
        private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);

        //API to change status of connection 
        [DllImport("iphlpapi.dll")]
        //private static extern int SetTcpEntry(MIB_TCPROW tcprow); 
        private static extern int SetTcpEntry(IntPtr pTcprow);

        //Convert 16-bit value from network to host byte order 
        [DllImport("wsock32.dll")]
        private static extern int ntohs(int netshort);

        //Convert 16-bit value back again 
        [DllImport("wsock32.dll")]
        private static extern int htons(int netshort);

        /// <summary> 
        /// Testexample 
        /// </summary> 
        public static void TEST()
        {
            Console.WriteLine("Not Working Yet!!!");
            //string[] ret = Connections(State.All);
            //foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
            //System.Diagnostics.Debug.WriteLine("----------------------------");
            //CloseRemotePort(1863);
            //CloseRemotePort(80);
            //ret = Connections(State.All);
            //foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
        }

        /// <summary> 
        /// Close all connection to the remote IP 
        /// </summary> 
        /// <param name="IP">IPen på remote PC</param> 
        public static void CloseRemoteIP(string IP)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (rows[i].dwRemoteAddr == IPStringToInt(IP))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
#if DEBUG
            Console.WriteLine(string.Format("RemoteIP {0} Closed", IP));
#endif
        }

        /// <summary> 
        /// Close all connections at current local IP 
        /// </summary> 
        /// <param name="IP"></param> 
        /// 
        public static void CloseLocalIP(string IP)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (rows[i].dwLocalAddr == IPStringToInt(IP))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Closes all connections to the remote port 
        /// </summary> 
        /// <param name="port"></param> 
        public static void CloseRemotePort(int port)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (port == ntohs(rows[i].dwRemotePort))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Closes all connections to the local port 
        /// </summary> 
        /// <param name="port"></param> 
        public static void CloseLocalPort(int port)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (port == ntohs(rows[i].dwLocalPort))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Close a connection by returning the connectionstring 
        /// </summary> 
        /// <param name="connectionstring"></param> 
        public static void CloseConnection(string connectionstring)
        {
            try
            {
                //Split the string to its subparts 
                string[] parts = connectionstring.Split('-');
                if (parts.Length != 4) throw new Exception("Invalid connectionstring - use the one provided by Connections.");
                string[] loc = parts[0].Split(':');
                string[] rem = parts[1].Split(':');
                string[] locaddr = loc[0].Split('.');
                string[] remaddr = rem[0].Split('.');

                //Fill structure with data 
                MIB_TCPROW row = new MIB_TCPROW();
                row.dwState = 12;
                byte[] bLocAddr = new byte[] { byte.Parse(locaddr[0]), byte.Parse(locaddr[1]), byte.Parse(locaddr[2]), byte.Parse(locaddr[3]) };
                byte[] bRemAddr = new byte[] { byte.Parse(remaddr[0]), byte.Parse(remaddr[1]), byte.Parse(remaddr[2]), byte.Parse(remaddr[3]) };
                row.dwLocalAddr = BitConverter.ToInt32(bLocAddr, 0);
                row.dwRemoteAddr = BitConverter.ToInt32(bRemAddr, 0);
                row.dwLocalPort = htons(int.Parse(loc[1]));
                row.dwRemotePort = htons(int.Parse(rem[1]));

                //Make copy of the structure into memory and use the pointer to call SetTcpEntry 
                IntPtr ptr = GetPtrToNewObject(row);
                int ret = SetTcpEntry(ptr);

                if (ret == -1) throw new Exception("Unsuccessful");
                if (ret == 65) throw new Exception("User has no sufficient privilege to execute this API successfully");
                if (ret == 87) throw new Exception("Specified port is not in state to be closed down");
                if (ret != 0) throw new Exception("Unknown error (" + ret + ")");

            }
            catch (Exception ex)
            {
                throw new Exception("CloseConnection failed (" + connectionstring + ")! [" + ex.GetType().ToString() + "," + ex.Message + "]");
            }
        }

        /// <summary> 
        /// Gets all connections 
        /// </summary> 
        /// <returns></returns> 
        public static string[] Connections()
        {
            return Connections(State.All);
        }

        /// <summary> 
        /// Gets a connection list of connections with a defined state 
        /// </summary> 
        /// <param name="state"></param> 
        /// <returns></returns> 
        public static string[] Connections(State state)
        {
            MIB_TCPROW[] rows = getTcpTable();

            ArrayList arr = new ArrayList();

            foreach (MIB_TCPROW row in rows)
            {
                if (state == State.All || state == (State)row.dwState)
                {
                    string localaddress = IPIntToString(row.dwLocalAddr) + ":" + ntohs(row.dwLocalPort);
                    string remoteaddress = IPIntToString(row.dwRemoteAddr) + ":" + ntohs(row.dwRemotePort);
                    arr.Add(localaddress + " - " + remoteaddress + " - " + ((State)row.dwState).ToString());
                }
            }

            return (string[])arr.ToArray(typeof(System.String));
        }

        //The function that fills the MIB_TCPROW array with connectioninfos 
        private static MIB_TCPROW[] getTcpTable()
        {
            IntPtr buffer = IntPtr.Zero; bool allocated = false;
            try
            {
                int iBytes = 0;
                GetTcpTable(IntPtr.Zero, ref iBytes, false); //Getting size of return data 
                buffer = Marshal.AllocCoTaskMem(iBytes); //allocating the datasize 

                allocated = true;

                GetTcpTable(buffer, ref iBytes, false); //Run it again to fill the memory with the data 

                int structCount = Marshal.ReadInt32(buffer); // Get the number of structures 

                IntPtr buffSubPointer = buffer; //Making a pointer that will point into the buffer 
                buffSubPointer = (IntPtr)((int)buffer + 4); //Move to the first data (ignoring dwNumEntries from the original MIB_TCPTABLE struct) 

                MIB_TCPROW[] tcpRows = new MIB_TCPROW[structCount]; //Declaring the array 

                //Get the struct size 
                MIB_TCPROW tmp = new MIB_TCPROW();
                int sizeOfTCPROW = Marshal.SizeOf(tmp);

                //Fill the array 1 by 1 
                for (int i = 0; i < structCount; i++)
                {
                    tcpRows[i] = (MIB_TCPROW)Marshal.PtrToStructure(buffSubPointer, typeof(MIB_TCPROW)); //copy struct data 
                    buffSubPointer = (IntPtr)((int)buffSubPointer + sizeOfTCPROW); //move to next structdata 
                }

                return tcpRows;

            }
            catch (Exception ex)
            {
                throw new Exception("getTcpTable failed! [" + ex.GetType().ToString() + "," + ex.Message + "]");
            }
            finally
            {
                if (allocated) Marshal.FreeCoTaskMem(buffer); //Free the allocated memory 
            }
        }

        private static IntPtr GetPtrToNewObject(object obj)
        {
            IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
            Marshal.StructureToPtr(obj, ptr, false);
            return ptr;
        }

        //Convert an IP string to the INT value 
        private static int IPStringToInt(string IP)
        {
            if (IP.IndexOf(".") < 0) throw new Exception("Invalid IP address");
            string[] addr = IP.Split('.');
            if (addr.Length != 4) throw new Exception("Invalid IP address");
            byte[] bytes = new byte[] { byte.Parse(addr[0]), byte.Parse(addr[1]), byte.Parse(addr[2]), byte.Parse(addr[3]) };
            return BitConverter.ToInt32(bytes, 0);
        }
        //Convert an IP integer to IP string 
        private static string IPIntToString(int IP)
        {
            byte[] addr = System.BitConverter.GetBytes(IP);
            return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
        }

    }
}
CIDR to RegEx: d-fault.nl/CIDRtoRegEx
DNS Lookup: d-fault.nl/DNSTools
DNSBL Lookup: d-fault.nl/DNSBLLookup
GEOIP Lookup: d-fault.nl/GeoipLookup

User avatar
mattg
Moderator
Moderator
Posts: 20291
Joined: 2007-06-14 05:12
Location: 'The Outback' Australia

Re: Check incoming connections with AbuseIPDB

Post by mattg » 2018-08-29 01:06

RvdH wrote:
2018-08-28 22:34
insomniac2k2 wrote:
2018-08-28 18:54
My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would
Well, how big a issue is that actually? The connection will time-out sooner or later... is it really necessary to forcefully close an auto-banned ipaddress ?
I think this happens a bit
More so recently.

In the last few weeks, I've seen a couple of times where i have 30+ active SMTP connections with no activity in my logs. Also my hMailserver often doesn't want to 'Stop', presumably due to open connections
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-29 04:16

More like hundreds. And while I understand that this should not be a problem with locking hmailserver threads, it seems to be very common in my installation. I know that as soon as i see a bunch of banned IPs that match up to what is presently connected to my server, i can count oh Hmailserver slowly trickling emails until I either restart the service or forcefully disconnecting those SMTP sessions. It almost seems like a bug of sorts, but i cannot put a finger on it. I can drastically accelerate and expose this issue by introducing a delay in the OnClientConnect sub.

My best guess is that I am running up against the Max number of commands or Asynchronous tasks threads limits. I've lightly tested this by increasing my max on all 3 thread limits, and I believe that I have seen the issue follow the relative amount that I adjusted by.
RvdH wrote:
2018-08-28 22:42
I can hardly believe that....what are we talking about here? Thousands and thousands of simultaneous connections and all being auto-banned?

You are aware this Cports is only triggered when an ipaddress is auto-banned, not whenever it tries to connect later on

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-29 04:18

Thanks for being my google :)

I did actually get cports to work by applying SorenR's suggestion, but I do like this and will give it a try a bit later next week.
RvdH wrote:
2018-08-28 23:47
In that case... 10kb :wink:
Source: stackoverflow.com

Code: Select all

using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace ConnectionManager
{
    class Disconnector
    {
    }

    public class Starter
    {
        public static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Disconnect IP1 [IP2 [IP3 [IPn]]]");
                Console.WriteLine("");
                Console.WriteLine("Connections up now:");
                string[] cons = Disconnecter.Connections(Disconnecter.State.Established);
                foreach (string s in cons)
                {
                    Console.WriteLine(s);
                }
            }
            else
            {
                foreach (string s in args)
                {
                    Disconnecter.CloseRemoteIP(s);
                }
            }
#if DEBUG
            Console.ReadKey();
#endif
        }
    }

    public class Disconnecter
    {

        /// <summary> 
        /// Enumeration of the states 
        /// </summary> 
        public enum State
        {
            /// <summary> All </summary> 
            All = 0,
            /// <summary> Closed </summary> 
            Closed = 1,
            /// <summary> Listen </summary> 
            Listen = 2,
            /// <summary> Syn_Sent </summary> 
            Syn_Sent = 3,
            /// <summary> Syn_Rcvd </summary> 
            Syn_Rcvd = 4,
            /// <summary> Established </summary> 
            Established = 5,
            /// <summary> Fin_Wait1 </summary> 
            Fin_Wait1 = 6,
            /// <summary> Fin_Wait2 </summary> 
            Fin_Wait2 = 7,
            /// <summary> Close_Wait </summary> 
            Close_Wait = 8,
            /// <summary> Closing </summary> 
            Closing = 9,
            /// <summary> Last_Ack </summary> 
            Last_Ack = 10,
            /// <summary> Time_Wait </summary> 
            Time_Wait = 11,
            /// <summary> Delete_TCB </summary> 
            Delete_TCB = 12
        }

        /// <summary> 
        /// Connection info 
        /// </summary> 
        private struct MIB_TCPROW
        {
            public int dwState;
            public int dwLocalAddr;
            public int dwLocalPort;
            public int dwRemoteAddr;
            public int dwRemotePort;
        }

        //API to get list of connections 
        [DllImport("iphlpapi.dll")]
        private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);

        //API to change status of connection 
        [DllImport("iphlpapi.dll")]
        //private static extern int SetTcpEntry(MIB_TCPROW tcprow); 
        private static extern int SetTcpEntry(IntPtr pTcprow);

        //Convert 16-bit value from network to host byte order 
        [DllImport("wsock32.dll")]
        private static extern int ntohs(int netshort);

        //Convert 16-bit value back again 
        [DllImport("wsock32.dll")]
        private static extern int htons(int netshort);

        /// <summary> 
        /// Testexample 
        /// </summary> 
        public static void TEST()
        {
            Console.WriteLine("Not Working Yet!!!");
            //string[] ret = Connections(State.All);
            //foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
            //System.Diagnostics.Debug.WriteLine("----------------------------");
            //CloseRemotePort(1863);
            //CloseRemotePort(80);
            //ret = Connections(State.All);
            //foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
        }

        /// <summary> 
        /// Close all connection to the remote IP 
        /// </summary> 
        /// <param name="IP">IPen på remote PC</param> 
        public static void CloseRemoteIP(string IP)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (rows[i].dwRemoteAddr == IPStringToInt(IP))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
#if DEBUG
            Console.WriteLine(string.Format("RemoteIP {0} Closed", IP));
#endif
        }

        /// <summary> 
        /// Close all connections at current local IP 
        /// </summary> 
        /// <param name="IP"></param> 
        /// 
        public static void CloseLocalIP(string IP)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (rows[i].dwLocalAddr == IPStringToInt(IP))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Closes all connections to the remote port 
        /// </summary> 
        /// <param name="port"></param> 
        public static void CloseRemotePort(int port)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (port == ntohs(rows[i].dwRemotePort))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Closes all connections to the local port 
        /// </summary> 
        /// <param name="port"></param> 
        public static void CloseLocalPort(int port)
        {
            MIB_TCPROW[] rows = getTcpTable();
            for (int i = 0; i < rows.Length; i++)
            {
                if (port == ntohs(rows[i].dwLocalPort))
                {
                    rows[i].dwState = (int)State.Delete_TCB;
                    IntPtr ptr = GetPtrToNewObject(rows[i]);
                    int ret = SetTcpEntry(ptr);
                }
            }
        }

        /// <summary> 
        /// Close a connection by returning the connectionstring 
        /// </summary> 
        /// <param name="connectionstring"></param> 
        public static void CloseConnection(string connectionstring)
        {
            try
            {
                //Split the string to its subparts 
                string[] parts = connectionstring.Split('-');
                if (parts.Length != 4) throw new Exception("Invalid connectionstring - use the one provided by Connections.");
                string[] loc = parts[0].Split(':');
                string[] rem = parts[1].Split(':');
                string[] locaddr = loc[0].Split('.');
                string[] remaddr = rem[0].Split('.');

                //Fill structure with data 
                MIB_TCPROW row = new MIB_TCPROW();
                row.dwState = 12;
                byte[] bLocAddr = new byte[] { byte.Parse(locaddr[0]), byte.Parse(locaddr[1]), byte.Parse(locaddr[2]), byte.Parse(locaddr[3]) };
                byte[] bRemAddr = new byte[] { byte.Parse(remaddr[0]), byte.Parse(remaddr[1]), byte.Parse(remaddr[2]), byte.Parse(remaddr[3]) };
                row.dwLocalAddr = BitConverter.ToInt32(bLocAddr, 0);
                row.dwRemoteAddr = BitConverter.ToInt32(bRemAddr, 0);
                row.dwLocalPort = htons(int.Parse(loc[1]));
                row.dwRemotePort = htons(int.Parse(rem[1]));

                //Make copy of the structure into memory and use the pointer to call SetTcpEntry 
                IntPtr ptr = GetPtrToNewObject(row);
                int ret = SetTcpEntry(ptr);

                if (ret == -1) throw new Exception("Unsuccessful");
                if (ret == 65) throw new Exception("User has no sufficient privilege to execute this API successfully");
                if (ret == 87) throw new Exception("Specified port is not in state to be closed down");
                if (ret != 0) throw new Exception("Unknown error (" + ret + ")");

            }
            catch (Exception ex)
            {
                throw new Exception("CloseConnection failed (" + connectionstring + ")! [" + ex.GetType().ToString() + "," + ex.Message + "]");
            }
        }

        /// <summary> 
        /// Gets all connections 
        /// </summary> 
        /// <returns></returns> 
        public static string[] Connections()
        {
            return Connections(State.All);
        }

        /// <summary> 
        /// Gets a connection list of connections with a defined state 
        /// </summary> 
        /// <param name="state"></param> 
        /// <returns></returns> 
        public static string[] Connections(State state)
        {
            MIB_TCPROW[] rows = getTcpTable();

            ArrayList arr = new ArrayList();

            foreach (MIB_TCPROW row in rows)
            {
                if (state == State.All || state == (State)row.dwState)
                {
                    string localaddress = IPIntToString(row.dwLocalAddr) + ":" + ntohs(row.dwLocalPort);
                    string remoteaddress = IPIntToString(row.dwRemoteAddr) + ":" + ntohs(row.dwRemotePort);
                    arr.Add(localaddress + " - " + remoteaddress + " - " + ((State)row.dwState).ToString());
                }
            }

            return (string[])arr.ToArray(typeof(System.String));
        }

        //The function that fills the MIB_TCPROW array with connectioninfos 
        private static MIB_TCPROW[] getTcpTable()
        {
            IntPtr buffer = IntPtr.Zero; bool allocated = false;
            try
            {
                int iBytes = 0;
                GetTcpTable(IntPtr.Zero, ref iBytes, false); //Getting size of return data 
                buffer = Marshal.AllocCoTaskMem(iBytes); //allocating the datasize 

                allocated = true;

                GetTcpTable(buffer, ref iBytes, false); //Run it again to fill the memory with the data 

                int structCount = Marshal.ReadInt32(buffer); // Get the number of structures 

                IntPtr buffSubPointer = buffer; //Making a pointer that will point into the buffer 
                buffSubPointer = (IntPtr)((int)buffer + 4); //Move to the first data (ignoring dwNumEntries from the original MIB_TCPTABLE struct) 

                MIB_TCPROW[] tcpRows = new MIB_TCPROW[structCount]; //Declaring the array 

                //Get the struct size 
                MIB_TCPROW tmp = new MIB_TCPROW();
                int sizeOfTCPROW = Marshal.SizeOf(tmp);

                //Fill the array 1 by 1 
                for (int i = 0; i < structCount; i++)
                {
                    tcpRows[i] = (MIB_TCPROW)Marshal.PtrToStructure(buffSubPointer, typeof(MIB_TCPROW)); //copy struct data 
                    buffSubPointer = (IntPtr)((int)buffSubPointer + sizeOfTCPROW); //move to next structdata 
                }

                return tcpRows;

            }
            catch (Exception ex)
            {
                throw new Exception("getTcpTable failed! [" + ex.GetType().ToString() + "," + ex.Message + "]");
            }
            finally
            {
                if (allocated) Marshal.FreeCoTaskMem(buffer); //Free the allocated memory 
            }
        }

        private static IntPtr GetPtrToNewObject(object obj)
        {
            IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
            Marshal.StructureToPtr(obj, ptr, false);
            return ptr;
        }

        //Convert an IP string to the INT value 
        private static int IPStringToInt(string IP)
        {
            if (IP.IndexOf(".") < 0) throw new Exception("Invalid IP address");
            string[] addr = IP.Split('.');
            if (addr.Length != 4) throw new Exception("Invalid IP address");
            byte[] bytes = new byte[] { byte.Parse(addr[0]), byte.Parse(addr[1]), byte.Parse(addr[2]), byte.Parse(addr[3]) };
            return BitConverter.ToInt32(bytes, 0);
        }
        //Convert an IP integer to IP string 
        private static string IPIntToString(int IP)
        {
            byte[] addr = System.BitConverter.GetBytes(IP);
            return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
        }

    }
}

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-29 04:33

I have this problem across 4 independent installations. Definitely more often now than before.
mattg wrote:
2018-08-29 01:06
RvdH wrote:
2018-08-28 22:34
insomniac2k2 wrote:
2018-08-28 18:54
My biggest issues is having remote servers keeping sessions open. I imagine if i get cports working, this issue would
Well, how big a issue is that actually? The connection will time-out sooner or later... is it really necessary to forcefully close an auto-banned ipaddress ?
I think this happens a bit
More so recently.

In the last few weeks, I've seen a couple of times where i have 30+ active SMTP connections with no activity in my logs. Also my hMailserver often doesn't want to 'Stop', presumably due to open connections

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-08-29 10:51

Well, I'm going to look at this: http://wkillcx.sourceforge.net/

Programmed in assembler, the language I started with before Anders Hejlsberg launched PolyPascal and TurboPascal 8)

Programming in assembler is a lost art. Later in life I got to work with terminal emulators (DCA IRMA 3270) and the initial versions were programmed in assembler (MS-DOS) ... 47 kb executeable to replace a IBM 3278 terminal complete with filetransfer and all. Then someone brilliantly suggested switching to C++ to enable native Windows 3.x mode ... The installation disc went from a 1.44 MB floppy to a fully packed CD :roll:
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-08-29 14:05

Just an update of testing this script with autoban and cports. I am seeing a drastic reduction of spam that is hitting my users junk email folder. I originally started using this at 40%. I have since adjusted it to 25%. I'm now considering around 15%. Before I do so, I'll do another spot check on anything near 15% to see if anything comes back legitimate.

On another note, I'm also testing SorenR's snowshoe verification. All I can say is wow. Snowshoe spammers had my companies on their VIP list or something. Near 8 thousand IP's banned in 2 days.

So now I guess we see exactly how large a ban list can get before hmail implodes....

antons
New user
New user
Posts: 16
Joined: 2016-01-18 12:46

Re: Check incoming connections with AbuseIPDB

Post by antons » 2018-10-23 10:48

Hello!

Which of these scripts will be worked on server2003R2?

User avatar
jimimaseye
Moderator
Moderator
Posts: 8171
Joined: 2011-09-08 17:48

Re: Check incoming connections with AbuseIPDB

Post by jimimaseye » 2018-10-23 12:32

The vbs should be independent of the os.
HMS 5.6.6 B2383 on Win Server 2008 R2 Foundation, + 5.6.7-B2415 on test.
SpamassassinForWindows 3.4.0 spamd service
AV: Clamwin + Clamd service + sanesecurity defs : https://www.hmailserver.com/forum/viewtopic.php?f=21&t=26829

antons
New user
New user
Posts: 16
Joined: 2016-01-18 12:46

Re: Check incoming connections with AbuseIPDB

Post by antons » 2018-10-24 13:17

I got the following error:

"ERROR" 2616 "2018-10-24 14:15:40.312" "Script Error: Source: msxml6.dll - Error: 800C0008 - Description: System error: -2146697208.[nl] - Line: 59 Column: 2 - Code: (null)"

Server 2003R2, Hmailserver 5.6.4

when use script from Po-In, posted 2018-05-24 13:46

User avatar
nitro
Normal user
Normal user
Posts: 33
Joined: 2018-11-08 16:31
Location: Spain

Re: Check incoming connections with AbuseIPDB

Post by nitro » 2018-11-08 16:43

I thought it would be more efficient for the script to add the ip to a firewall rule in windows, thus preventing the same ip from reaching the mail server. It is necessary to optimize the code and control the limit of ip's as a rule.

Code: Select all


.......	Percentage = "0" 'Default value
	Dim objShell
	Dim objExec
	Dim strPSResults
	Dim stAllIpBaned


'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage= CheckAbuseIPDBConfidence(ClientIP)

'Process reported percentage		
		If Percentage > 40 then
			Result.Value = 1
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rechazado: % en AbuseIPDB: " & Percentage & "%.")
			' Add to firewall rule
				' Create shell object
				Set objShell = CreateObject("Wscript.Shell")
				' Execute the combined command
				Set objExec = objShell.Exec("powershell -windowstyle hidden -command (Get-NetFirewallRule -DisplayName Ban_IP | Get-NetFirewallAddressFilter ).RemoteAddress")
				' Read output into VBS variable
				strPSResults = objExec.StdOut.ReadAll
				stAllIpBaned = ClientIP
				' Replace in output powershell 
	 			strPSResults = Replace(strPSResults, chr(13), ",",1,1000) ' Max RemoteAddress in W2016 srv
				strPSResults = Replace(strPSResults, chr(10), "",1,1000)
				' Add detected ip to output powershell
				stAllIpBaned = strPSResults + stAllIpBaned
				' Send old ip's and new ip to Firewall Rule
				Set objExec = objShell.Exec("powershell -windowstyle hidden -command Set-NetFirewallRule -DisplayName Ban_IP -RemoteAddress"&" "&stAllIpBaned)
				Set objShell = Nothing
		
		ElseIf Percentage > 10 then
			Result.Value = 0..............
Production 5.6.8-B2437.20_OpenSSL_1.0.2s W.Server 2016 Datace [2x Intel Xeon E5-2660 8GB RAM]
Staging 5.7-B2490 W.Server 2008 R2 Stand [Intel Pentium 4 4GB RAM]

User avatar
nitro
Normal user
Normal user
Posts: 33
Joined: 2018-11-08 16:31
Location: Spain

Re: Check incoming connections with AbuseIPDB

Post by nitro » 2018-11-12 13:38

I paste here the modified @ Po-In code so that it automatically inserts the ip addresses detected in a ban rule ip. I believe that in this way the load of Hmailserver will be reduced by not having to make new queries of the same ip in AbuseIPDB. Use Windows Server 2016, where supposedly it is allowed to add up to 10,000 ip's on the same rule, since I use Hmailserver in an environment with few email accounts I think that, for me, it is enough with an email notification when the rule is being filled.
I have been using Hmailserver since 2012 when, due to circumstances of life and crisis, I was assigned the task of installing and maintaining a mail server. From here I want to thank the creator and the whole community for having facilitated my task. Thank you.

Code: Select all

Sub OnClientConnect(oClient)
	ClientIp = oClient.IpAddress 'Connecting remote IP address
	WhiteList = "#127.0.0.1#1.2.3.4" 'Variable array for whitelisted IP addresses to exclude, localhost, maybe your servers IP address, your WebClient IP address whatever
	Percentage = "0" 'Default value
	Dim objShell
	Dim objExec
	Dim strPSResults
	Dim ip
	

'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage= CheckAbuseIPDBConfidence(ClientIP)

'Process reported percentage		
		If Percentage > 40 then
			Result.Value = 1
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected: Confidence of Abuse: " & Percentage & "%.")
			' Add to firewall rule
				' Create shell object
				Set objShell = CreateObject("Wscript.Shell")
				' Execute the combined command
				Set objExec = objShell.Exec("powershell -windowstyle hidden -command (Get-NetFirewallRule -DisplayName Ban_IP | Get-NetFirewallAddressFilter ).RemoteAddress")
				' Read output into VBS variable
				strPSResults = objExec.StdOut.ReadAll
				ip = ClientIP
				' Replace in output powershell 
				strPSResults = Replace(strPSResults, chr(13), ",",1,10000)
				strPSResults = Replace(strPSResults, chr(10), "",1,10000)
				if len(strPSResults) - len(replace(strPSResults, ",", "")) > 9000  then ' Alert max 10.000 ips per rule
					EventLog.Write ("**** ATTENTION RULE BAN_IP 90%  ****")  ' Write in log file
					' Send email Alert max 10.000 ips per rule
						dim MessageRecipientName, MessageRecipientAddress, MessageSubject
						dim oApp, sBackupLog, oMessage
						Set oApp = CreateObject("hMailServer.Application")
						MessageRecipientName = "MAIL SERVER"  'CHANGE ME
						MessageRecipientAddress = "recipient@address.com"  'CHANGE ME
						MessageSubject = "ATTENTION RULE BAN_IP 90%"
						Call oApp.Authenticate("useradmin", "password")
						Set oMessage = CreateObject("hMailServer.Message")
						oMessage.From = "hMailServer" & "<recipient@address.com>"
						oMessage.FromAddress = "from@addresses.com"
						oMessage.Subject = MessageSubject
						oMessage.AddRecipient MessageRecipientName, MessageRecipientAddress
						oMessage.Body = "ATTENTION RULE BAN_IP 90%." & vbNewLine & vbNewLine & sBackupLog			
						oMessage.Save
					' End Send email Alert max 10.000 ips per rule
				END If 
				' Add detected ip to output powershell
				ip = strPSResults + ip
				' Send old ip's and new ip to Firewall Rule
					Set objExec = objShell.Exec("powershell -windowstyle hidden -command Set-NetFirewallRule -DisplayName Ban_IP -RemoteAddress"&" "&ip)
					Set objShell = Nothing
			' End Add to firewall
			ElseIf 
			Result.Value = 0
		End If
	End If
End Sub

Public Function CheckAbuseIPDBConfidence(IPAddress)
	CheckAbuseIPDBConfidence = "0"
	Set objXMLHTTP = CreateObject("msxml2.xmlhttp.6.0")
		objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & IPAddress, False
		objXMLHTTP.Send ""
		ResponseText = objXMLHTTP.responseText
		ResponseArray = Split(ResponseText, VbLf)
		For Each ResponseLine in ResponseArray
			If Left(ResponseLine, 6) = "<span>" And Right(ResponseLine, 8) = "%</span>" Then
				CheckAbuseIPDBConfidence = Mid(ResponseLine,7, Len(ResponseLine)-14)
				Exit For
			End If
		Next	
	Set objXMLHTTP = Nothing
End Function	
Production 5.6.8-B2437.20_OpenSSL_1.0.2s W.Server 2016 Datace [2x Intel Xeon E5-2660 8GB RAM]
Staging 5.7-B2490 W.Server 2008 R2 Stand [Intel Pentium 4 4GB RAM]

df5zx
New user
New user
Posts: 1
Joined: 2018-11-24 16:27

Re: Check incoming connections with AbuseIPDB

Post by df5zx » 2018-11-24 16:31

Hello everybody,

I wanted to try that as well, but I do get the same error like Antons:

Script Error: Source: msxml6.dll - Error: 800C0008 - Description: System error: -2146697208.

What could it be ???

tnx for help,

Jürgen

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-12-05 20:28

Thanks for your contribution Nitro. I've done Windows firewall bans from script before, but im giving this a try again. I really like the prospect to reducing bans on Hmail and putting the load on Windows better.

In my case, I have near 80,000 bans in Hmail. I've kind of been watching it like a science experiment. It's pretty nasty to parse the IP Range list when you want to take a look in the UI. This type of ban mitigates that issue.
nitro wrote:
2018-11-12 13:38
I paste here the modified @ Po-In code so that it automatically inserts the ip addresses detected in a ban rule ip. I believe that in this way the load of Hmailserver will be reduced by not having to make new queries of the same ip in AbuseIPDB. Use Windows Server 2016, where supposedly it is allowed to add up to 10,000 ip's on the same rule, since I use Hmailserver in an environment with few email accounts I think that, for me, it is enough with an email notification when the rule is being filled.
I have been using Hmailserver since 2012 when, due to circumstances of life and crisis, I was assigned the task of installing and maintaining a mail server. From here I want to thank the creator and the whole community for having facilitated my task. Thank you.

Code: Select all

Sub OnClientConnect(oClient)
	ClientIp = oClient.IpAddress 'Connecting remote IP address
	WhiteList = "#127.0.0.1#1.2.3.4" 'Variable array for whitelisted IP addresses to exclude, localhost, maybe your servers IP address, your WebClient IP address whatever
	Percentage = "0" 'Default value
	Dim objShell
	Dim objExec
	Dim strPSResults
	Dim ip
	

'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage= CheckAbuseIPDBConfidence(ClientIP)

'Process reported percentage		
		If Percentage > 40 then
			Result.Value = 1
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected: Confidence of Abuse: " & Percentage & "%.")
			' Add to firewall rule
				' Create shell object
				Set objShell = CreateObject("Wscript.Shell")
				' Execute the combined command
				Set objExec = objShell.Exec("powershell -windowstyle hidden -command (Get-NetFirewallRule -DisplayName Ban_IP | Get-NetFirewallAddressFilter ).RemoteAddress")
				' Read output into VBS variable
				strPSResults = objExec.StdOut.ReadAll
				ip = ClientIP
				' Replace in output powershell 
				strPSResults = Replace(strPSResults, chr(13), ",",1,10000)
				strPSResults = Replace(strPSResults, chr(10), "",1,10000)
				if len(strPSResults) - len(replace(strPSResults, ",", "")) > 9000  then ' Alert max 10.000 ips per rule
					EventLog.Write ("**** ATTENTION RULE BAN_IP 90%  ****")  ' Write in log file
					' Send email Alert max 10.000 ips per rule
						dim MessageRecipientName, MessageRecipientAddress, MessageSubject
						dim oApp, sBackupLog, oMessage
						Set oApp = CreateObject("hMailServer.Application")
						MessageRecipientName = "MAIL SERVER"  'CHANGE ME
						MessageRecipientAddress = "recipient@address.com"  'CHANGE ME
						MessageSubject = "ATTENTION RULE BAN_IP 90%"
						Call oApp.Authenticate("useradmin", "password")
						Set oMessage = CreateObject("hMailServer.Message")
						oMessage.From = "hMailServer" & "<recipient@address.com>"
						oMessage.FromAddress = "from@addresses.com"
						oMessage.Subject = MessageSubject
						oMessage.AddRecipient MessageRecipientName, MessageRecipientAddress
						oMessage.Body = "ATTENTION RULE BAN_IP 90%." & vbNewLine & vbNewLine & sBackupLog			
						oMessage.Save
					' End Send email Alert max 10.000 ips per rule
				END If 
				' Add detected ip to output powershell
				ip = strPSResults + ip
				' Send old ip's and new ip to Firewall Rule
					Set objExec = objShell.Exec("powershell -windowstyle hidden -command Set-NetFirewallRule -DisplayName Ban_IP -RemoteAddress"&" "&ip)
					Set objShell = Nothing
			' End Add to firewall
			ElseIf 
			Result.Value = 0
		End If
	End If
End Sub

Public Function CheckAbuseIPDBConfidence(IPAddress)
	CheckAbuseIPDBConfidence = "0"
	Set objXMLHTTP = CreateObject("msxml2.xmlhttp.6.0")
		objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & IPAddress, False
		objXMLHTTP.Send ""
		ResponseText = objXMLHTTP.responseText
		ResponseArray = Split(ResponseText, VbLf)
		For Each ResponseLine in ResponseArray
			If Left(ResponseLine, 6) = "<span>" And Right(ResponseLine, 8) = "%</span>" Then
				CheckAbuseIPDBConfidence = Mid(ResponseLine,7, Len(ResponseLine)-14)
				Exit For
			End If
		Next	
	Set objXMLHTTP = Nothing
End Function	

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-12-10 04:52

I figured I should post a little logic that I added for the ban rule. I'm running windows 2012R2 presently, and it seems like the ban list is limited to 1000 entries. On a busy day, I can fill 1. In order to mitigate this and also mitigate running out of ban space, use the scripting below to copy your existing ban list, rename it, and clean your active list. Thus making room for 999 (in my case 989) fresh new scumbag ip addresses. I implemented this yesterday, and I'm already on my 2nd rule. If you care about possible overlap of rules, just add something like Time to the curDate variable. Works great!

Add all code below "If len"

Code: Select all

	
	Dim curDate
	curDate =  "_" & Month(Date) & "_" & Day(Date) & "_" & Year(Date)
	Set objShell = CreateObject("Wscript.Shell")
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command copy-netfirewallrule -name Hmailblock -newname"&" Hmailblock"&curDate)
	Wait(1)
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command get-netfirewallrule -name"&" Hmailblock"&curDate& " | set-netfirewallrule -newdisplayname Hmailblock"&curDate)
	Wait(1)
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command set-netfirewallrule -displayname Hmailblock -RemoteAddress 55.55.55.55")	'this can be any IP really. It just clears the list. Yeah I know its lazy...
	EventLog.Write ("**** ATTENTION RULE BAN_IP 99%, Creating new firewall rule ****")  ' Write in log file
	
You need the "Wait" Function to make this logic work:

Code: Select all

Function Wait(sec)
  With CreateObject("WScript.Shell")
	 .Run "timeout /T " & Int(sec), 0, True
'        .Run "sleep -m " & Int(sec * 1000), 0, True
'        .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
  End With
End Function

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-10 15:31

There is a way to control your Firewall witn VBScript (Windows 7 and up) using the COM API of Windows Firewall with Advanced Security (WFAS).

My systems are pre-Windows 7 :oops: Eventually I will update them but I found that the only object NOT supported by my server is ** CreateObject("HNetCfg.FwPolicy2") ** :roll:

Sample code...
http://www.ohmancorp.com/files/RefWin-A ... WRules.txt

https://docs.microsoft.com/da-dk/previo ... -exception

And... I came across this one...

Code: Select all

' http://psscripts.blogspot.com/2012/12/automatically-block-rdp-attacks-on-your.html

' fail2ban.vbs:

If wscript.arguments.count = 2 then
    Dim firewall, rule, rulename, ip, re, account
    'Change this value! This rule must already exist in your inbound firewall rules
    rulename = "Fail2Ban"

    account = wscript.arguments.item(0)
    ip = wscript.arguments.item(1)
    'MsgBox "Debug message: Invalid login with account " & account & " from IP " & ip
    Set re = new regexp
    re.Pattern = "\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b"

    If re.Test(ip) And Not IsException(account, ip) Then
        Set firewall  = CreateObject("HNetCfg.FwPolicy2")
        Set rule = firewall.Rules.Item(rulename)
        If Not (rule Is Nothing) Then
            If InStr(1,rule.RemoteAddresses,ip,1) = 0 Then
                rule.RemoteAddresses = rule.RemoteAddresses & "," & ip
            End If
        End If
        Set firewall = Nothing
    Else
        'Invalid IP or excemption from rule
    End If
end If

'Handle exception cases here, you don't want to ban your own IP, for instance...Customize to your needs
Function IsException(account, ip)

  Dim exip
  exip = "My.IP"
  IsException = False

  If ip = exip Then
    IsException = True
  End If
End Function
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-12-10 22:29

Go 2019. :) 1000 bans per list!

I say that, because for me it's really easy. I use hmailserver as a hardened relay. I'd hate to have to migrate to a more updated server..
SorenR wrote:
2018-12-10 15:31
There is a way to control your Firewall witn VBScript (Windows 7 and up) using the COM API of Windows Firewall with Advanced Security (WFAS).

My systems are pre-Windows 7 :oops: Eventually I will update them but I found that the only object NOT supported by my server is ** CreateObject("HNetCfg.FwPolicy2") ** :roll:

Sample code...
http://www.ohmancorp.com/files/RefWin-A ... WRules.txt

https://docs.microsoft.com/da-dk/previo ... -exception

And... I came across this one...

Code: Select all

' http://psscripts.blogspot.com/2012/12/automatically-block-rdp-attacks-on-your.html

' fail2ban.vbs:

If wscript.arguments.count = 2 then
    Dim firewall, rule, rulename, ip, re, account
    'Change this value! This rule must already exist in your inbound firewall rules
    rulename = "Fail2Ban"

    account = wscript.arguments.item(0)
    ip = wscript.arguments.item(1)
    'MsgBox "Debug message: Invalid login with account " & account & " from IP " & ip
    Set re = new regexp
    re.Pattern = "\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b"

    If re.Test(ip) And Not IsException(account, ip) Then
        Set firewall  = CreateObject("HNetCfg.FwPolicy2")
        Set rule = firewall.Rules.Item(rulename)
        If Not (rule Is Nothing) Then
            If InStr(1,rule.RemoteAddresses,ip,1) = 0 Then
                rule.RemoteAddresses = rule.RemoteAddresses & "," & ip
            End If
        End If
        Set firewall = Nothing
    Else
        'Invalid IP or excemption from rule
    End If
end If

'Handle exception cases here, you don't want to ban your own IP, for instance...Customize to your needs
Function IsException(account, ip)

  Dim exip
  exip = "My.IP"
  IsException = False

  If ip = exip Then
    IsException = True
  End If
End Function

User avatar
nitro
Normal user
Normal user
Posts: 33
Joined: 2018-11-08 16:31
Location: Spain

Re: Check incoming connections with AbuseIPDB

Post by nitro » 2018-12-13 17:19

insomniac2k2 wrote:
2018-12-10 04:52
I figured I should post a little logic that I added for the ban rule. I'm running windows 2012R2 presently, and it seems like the ban list is limited to 1000 entries. On a busy day, I can fill 1. In order to mitigate this and also mitigate running out of ban space, use the scripting below to copy your existing ban list, rename it, and clean your active list. Thus making room for 999 (in my case 989) fresh new scumbag ip addresses. I implemented this yesterday, and I'm already on my 2nd rule. If you care about possible overlap of rules, just add something like Time to the curDate variable. Works great!

Add all code below "If len"

Code: Select all

	
	Dim curDate
	curDate =  "_" & Month(Date) & "_" & Day(Date) & "_" & Year(Date)
	Set objShell = CreateObject("Wscript.Shell")
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command copy-netfirewallrule -name Hmailblock -newname"&" Hmailblock"&curDate)
	Wait(1)
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command get-netfirewallrule -name"&" Hmailblock"&curDate& " | set-netfirewallrule -newdisplayname Hmailblock"&curDate)
	Wait(1)
	Set objExec = objShell.Exec("powershell -windowstyle hidden -command set-netfirewallrule -displayname Hmailblock -RemoteAddress 55.55.55.55")	'this can be any IP really. It just clears the list. Yeah I know its lazy...
	EventLog.Write ("**** ATTENTION RULE BAN_IP 99%, Creating new firewall rule ****")  ' Write in log file
	
You need the "Wait" Function to make this logic work:

Code: Select all

Function Wait(sec)
  With CreateObject("WScript.Shell")
	 .Run "timeout /T " & Int(sec), 0, True
'        .Run "sleep -m " & Int(sec * 1000), 0, True
'        .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
  End With
End Function

I will use your solution, unfortunately the maximum size that can be passed in a parameter is limited to 32700 characters. 15 characters per ip 2180 ip.

From that size we will get a nice error in our log:
Script Error: Source: WshShell.Exec - Error: 800700CE - Description: The filename or extension is too long.
Production 5.6.8-B2437.20_OpenSSL_1.0.2s W.Server 2016 Datace [2x Intel Xeon E5-2660 8GB RAM]
Staging 5.7-B2490 W.Server 2008 R2 Stand [Intel Pentium 4 4GB RAM]

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-12-16 17:08

While the rolling ban rule logic that I posted above works fine, I have really busy servers. I've found that I can have up to 10 redundant attempts to create a new rule at a time. Fortunately only one can be created by using my logic, but it causes a bit of hammering. I decided to break out the firewall rule count check into a separate script and call it from task scheduler every 5 minutes. This keep all verification logic off the event handler and lets it do what it does best.

Here is the code that I call from task scheduler if anyone is interested:

MakeFirewallrule.vbs -

Code: Select all

Dim datevalue, dtsnow, dtsvalue, timevalue, curDate
Dim dd, mm, yy, hh, nn, ss

'Individual date components
dtsnow = Now()
dd = Right("00" & Day(dtsnow), 2)
mm = Right("00" & Month(dtsnow), 2)
yy = Year(dtsnow)
hh = Right("00" & Hour(dtsnow), 2)
nn = Right("00" & Minute(dtsnow), 2)
ss = Right("00" & Second(dtsnow), 2)
timevalue = hh & "-" & nn & "-" & ss
datevalue = yy & "-" & mm & "-" & dd
curDate =  "_" & Month(Date) & "_" & Day(Date) & "_" & Year(Date) & "_" & timevalue

'verify how many IP's are in firewall rule and create rule if needed
		' Create shell object
		Set objShell = CreateObject("Wscript.Shell")
		' Execute the combined command
		Set objExec = objShell.Exec("powershell -windowstyle hidden -command (Get-NetFirewallRule -DisplayName Hmailblock | Get-NetFirewallAddressFilter ).RemoteAddress")
		' Read output into VBS variable
		strPSResults = objExec.StdOut.ReadAll
		' Replace in output powershell 
		strPSResults = Replace(strPSResults, chr(13), ",",1,1000)
		strPSResults = Replace(strPSResults, chr(10), "",1,1000)
	if len(strPSResults) - len(replace(strPSResults, ",", "")) > 995  then ' Alert max 1000 ips per rule
		Set objShell = CreateObject("Wscript.Shell")
		Set objExec = objShell.Exec("powershell -windowstyle hidden -command copy-netfirewallrule -name Hmailblock -newname"&" Hmailblock"&curDate)
		Wait(2)
		Set objExec = objShell.Exec("powershell -windowstyle hidden -command get-netfirewallrule -name"&" Hmailblock"&curDate& " | set-netfirewallrule -newdisplayname Hmailblock"&curDate)
		Wait(2)
		Set objExec = objShell.Exec("powershell -windowstyle hidden -command set-netfirewallrule -displayname Hmailblock -RemoteAddress 55.55.55.55")
	END If 


Function Wait(sec)
  With CreateObject("WScript.Shell")
	 .Run "timeout /T " & Int(sec), 0, True
'        .Run "sleep -m " & Int(sec * 1000), 0, True
'        .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
  End With
End Function
I call this vbs from this batch file. You can do it whatever way works in windows for you:

makenewfirewallrulewhenfull.cmd -

Code: Select all

@echo off
pushd "C:\Program Files (x86)\hMailServer\Events"
cscript makenewfirewallrule.vbs
exit
The rolling firewall rules end up looking like the attached image. I strip out the redundant 55.55.55.55 ip's every once in a while. Some day when i care, I will strip it out with code.
firewall_rules.PNG

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-16 19:05

I built a simple IDS / PortMonitor using tables in the database. It was either DB access or reading and writing files as I needed to pass data across multiple hMailServer triggers. File handling and session locking sucks :mrgreen: so I turned to SQLLite at first and later to MySQL as this is used by my server.

IDS: External connection from server that never progresses to actually sending mail will become autobanned after 3 "hits".
Functionality:
OnClientConnect will check IP Address in DB, if exist AND above limit -> Autoban.
IF exist AND below limit -> increment counter.
IF connection results in sending an email, the IP Address is removed from DB immediately.

PortMon: ANY connection attempt from "illegal" countries are logged, after 5 attempts they are autobanned.

Both tables are monitored by a script via Scheduler in order to remove old entries and prevent tables from growing uncontrolled.

Maybe you can use this as inspiration on how to offload some of the work from hMailServer.

I envision that any IP Address destined for the Firewall is simply added to the table and the connection is disconnected with a "Result.Value=1". Any further processing is then handled by an external process reading the DB tables and updating the Firewall apropriately. Benefit is that multiple mailservers can deliver "bad" IP Addresses into the queue and update a dedicated Firewall.

Code: Select all

'******************************************************************************************************************************
'********** hMailServer IDS Code (MySQL)                                                                             **********
'******************************************************************************************************************************

Private Const idsDBDrv = "DRIVER={MySQL ODBC 5.3 Unicode Driver};Database=#DB#;Uid=#UID#;Pwd=#PWD#;Option=3;"
Private Const idsTab01 = "hm_ids"
Private Const idsHit01 = 3
Private Const idsMins  = 120
Private Const idsTab02 = "hm_portmon"
Private Const idsHit02 = 5

'   DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Port=3306;Database=#DB#;Uid=#UID#;Pwd=#PWD#;Option=3;

'   Table:   CREATE TABLE %ids% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   hits      INTEGER);"

'   Table:   CREATE TABLE %portmon% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   port      INTEGER,
'                   hits      INTEGER);"

'* Function idsDBMaint()
'*    Dim oConn : Set oConn = CreateObject("ADODB.Connection")
'*    oConn.Open idsDBDrv
'*    If oConn.State <> 1 Then
'*       EventLog.Write( "idsDBMaint - ERROR: Could not connect" )
'*       Exit Function
'*    End If
'*    oConn.Execute "DELETE FROM " & idsTab01 & " WHERE DATE_ADD(timestamp, INTERVAL 12 HOUR) < NOW();"
'*    oConn.Execute "DELETE FROM " & idsTab02 & " WHERE DATE_ADD(timestamp, INTERVAL 24 HOUR) < NOW();"
'*    oConn.Close
'* End Function

Function idsDelete(sIPAddress)
   Dim oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsDelete - ERROR: Could not connect" )
      Exit Function
   End If
   oConn.Execute "DELETE FROM " & idsTab01 & " WHERE ipaddress = '" & sIPAddress & "';"
   oConn.Close
End Function

Function idsCheck(sIPAddress) : idsCheck = False
   Dim oRecord, oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsCheck - ERROR: Could not connect" )
      Exit Function
   End If
   On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTab01 & " WHERE ipaddress='" & sIPAddress & "';")
   On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "idsCheck - ERROR: Table " & idsTab01 & " does not exist!" )
      Exit Function
   End If
   If oRecord.BOF And oRecord.EOF Then '   IPAddress is NEW!
      oConn.Execute "INSERT IGNORE INTO " & idsTab01 & " (timestamp,ipaddress,hits) VALUES (NOW(),'" & sIPAddress & "',0);"
      oConn.Execute "UPDATE " & idsTab01 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
   Else '   In case of more than one record, unlikely since "ipaddress" have a UNIQUE constraint.
      While Not oRecord.EOF
         idsCheck = (oRecord("hits") >= idsHit01)
         If (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then '   IPAddress is known - but too old.
            oConn.Execute "UPDATE " & idsTab01 & " SET hits=1,timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         Else '   IPAddress is known - bump counter.
            oConn.Execute "UPDATE " & idsTab01 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         End If
         oRecord.MoveNext
      Wend
   End If
   oRecord.Close
   oConn.Close
End Function

Function idsPortMon(sIPAddress, iPort) : idsPortMon = False
   Dim oRecord, oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsPortMon - ERROR: Could not connect" )
      Exit Function
   End If
   On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTab02 & " WHERE ipaddress='" & sIPAddress & "';")
   On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "idsPortMon - ERROR: Table " & idsTab02 & " does not exist!" )
      Exit Function
   End If
   If oRecord.BOF And oRecord.EOF Then '   IPAddress is NEW!
      oConn.Execute "INSERT IGNORE INTO " & idsTab02 & " (timestamp,ipaddress,port,hits) VALUES (NOW(),'" & sIPAddress & "'," & iPort & ",0);"
      oConn.Execute "UPDATE " & idsTab02 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
   Else '   IPAddress is known - bump counter.
      While Not oRecord.EOF
         idsPortMon = (oRecord("hits") >= idsHit02)
         oConn.Execute "UPDATE " & idsTab02 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         oRecord.MoveNext
      Wend
   End If
   oRecord.Close
   oConn.Close
End Function

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

'   System Scripting Runtime COM object ("SScripting.IPNetwork")
'   http://www.netal.com/ssr.htm
'   Binary -> http://www.netal.com/software/ssr15.zip
'   http://countries.nerd.dk/isolist.txt

Function NerdLookup(strIP)
   Dim a
   a = Split(strIP, ".")
   With CreateObject("SScripting.IPNetwork")
      strIP = .DNSLookup(a(3) & "." & a(2) & "." & a(1) & "." & a(0) & ".zz.countries.nerd.dk")
   End With
   If Left(strIP, 3) <> "127" Then
      NerdLookup = "000"
   Else
      a = Split(strIP, ".")
      NerdLookup = Right("00" & CStr(a(2)*256 + a(3)), 3)
   End If
End Function

'******************************************************************************************************************************
'********** hMailServer Triggers                                                                                     **********
'******************************************************************************************************************************

Sub OnClientConnect(oClient)
   Dim strPort

   '   Only allow non-SMTP connect from "Rigsfællesskabet"/"Naalagaaffeqatigiit"/"Ríkisfelagsskapurin" = The Danish Realm.
   '   000 = N/A, 208 = Denmark, 304 = Greenland, 234 = Faroe Islands
   If (oClient.Port <> 25) Then
      If InStr("|208|304|234|", NerdLookup(oClient.IPAddress)) = 0 Then
         If idsPortMon(oClient.IPAddress, oClient.Port) Then
            Result.Value = 1
            strPort = Trim(Mid("SMTP IMAP SMTPSSUBM IMAPS", InStr("25   143  465  587  993  ", oClient.Port), 5))
            If AutoBan(oClient.IPAddress, "PORTBLOCK - " & strPort, 1, "d") Then _
               EventLog.Write( "AutoBan(" & oClient.IPAddress & ", PORTBLOCK - " & strPort & ", 1, d)" )
            Exit Sub
         Else
            Result.Value = 1
            Exit Sub
         End If
      End If
   End If

   '   Only test SMTP traffic
   If InStr("|25|587|465|", oClient.Port) > 0 Then
      If idsCheck(oClient.IPAddress) Then
         Result.Value = 1
         If AutoBan(oClient.IPAddress, "IDS", 7, "d") Then _
            EventLog.Write( "AutoBan(" & oClient.IPAddress & ", IDS, 7, d)" )
         Exit Sub
      End If
   End If
End Sub


Sub OnAcceptMessage(oClient, oMessage)

   '   Cleanup IDS registry
   idsDelete(oClient.IPAddress)

End Sub
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-16 19:49

Just a note...

hMailServer API have an object (Database) used to WRITE to the system database using ExecuteSQL, ExecuteSQLScript or ExecuteSQLWithReturn.

Unfortunately there is NO way to READ from the database using the API. BUT... If all you need to do is to dump IP Addresses to an external script, that is one way to do it.

Could be like this... :mrgreen:

Code: Select all

If isBAD(oClient.IPAddress) Then
   DumpToDB(oClient.IPAddress)
   Result.Value = 1
   Exit Sub
End If
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

insomniac2k2
Normal user
Normal user
Posts: 84
Joined: 2016-08-09 19:47

Re: Check incoming connections with AbuseIPDB

Post by insomniac2k2 » 2018-12-17 01:55

Thanks for sharing this code. Some day in the future I plan on doing quite a bit with some custom whitelisting, as well as doing stuff quite similar to what you are doing with this IDS code.

I love the thought of a central database database, as I run about 10 hmail based servers as hardened relays. At the moment, these servers slowly build their own lists. One list to rule them all have obvious benefits!

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-17 02:08

"One list to rule them all, One list to find them, One list to bring them all and in the darkness bind them." :mrgreen:
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

User avatar
nitro
Normal user
Normal user
Posts: 33
Joined: 2018-11-08 16:31
Location: Spain

Re: Check incoming connections with AbuseIPDB

Post by nitro » 2018-12-19 11:54

SorenR wrote:
2018-12-16 19:05
I built a simple IDS / PortMonitor using tables in the database. It was either DB access or reading and writing files as I needed to pass data across multiple hMailServer triggers. File handling and session locking sucks :mrgreen: so I turned to SQLLite at first and later to MySQL as this is used by my server.
No MSSQL, no party....
SorenR wrote:
2018-12-17 02:08
"One list to rule them all, One list to find them, One list to bring them all and in the darkness bind them." :mrgreen:
Three List's for the big bosses under the sky,
Seven for the Dwarf-users in their halls of stone,
Nine for VIP Men doomed to die,
One for the Admin Lord on his dark throne
In the Land of Hmailserver where the Shadows lie.

Merry Christmas. :D
Production 5.6.8-B2437.20_OpenSSL_1.0.2s W.Server 2016 Datace [2x Intel Xeon E5-2660 8GB RAM]
Staging 5.7-B2490 W.Server 2008 R2 Stand [Intel Pentium 4 4GB RAM]

User avatar
nitro
Normal user
Normal user
Posts: 33
Joined: 2018-11-08 16:31
Location: Spain

Re: Check incoming connections with AbuseIPDB

Post by nitro » 2018-12-20 13:49

After a while using the code I have been able to observe that for my server it is enough to have a firewall rule for each month. Something as simple as concatenating the month and the year after the name of the rule allows me to have created 12 rules for the next year and only review them if at any time it exceeds 2000 ip's.

Code: Select all

Sub OnClientConnect(oClient)
	ClientIp = oClient.IpAddress 'Connecting remote IP address
	WhiteList = "#127.0.0.1#1.2.3.4" 'Variable array for whitelisted IP addresses to exclude, localhost, maybe your servers IP address, your WebClient IP address whatever
	Percentage = "0" 'Default value
	Dim objShell
	Dim objExec
	Dim strPSResults
	Dim ip
	

	'Check if connecting client isn't whitelisted
	If Instr(WhiteList, "#" & ClientIp & "#") = 0 Then
		Percentage= CheckAbuseIPDBConfidence(ClientIP) 'Check % in AbuseIPDB

	'Process reported percentage		
		If Percentage > 40 then
			Result.Value = 1
			EventLog.Write ("AbuseIPDB: IP Address " & ClientIp & " rejected: Confidence of Abuse: " & Percentage & "%.")
			' Add to firewall rule
				
			' Create shell object
		    	Set objShell = CreateObject("Wscript.Shell")

			' Execute the combined command
			Set objExec = objShell.Exec("powershell -windowstyle hidden -command (Get-NetFirewallRule -DisplayName Ban_IP" & Month(Date()) & Year(Date()) &" | Get-NetFirewallAddressFilter ).RemoteAddress")
			' Read output into VBS variable
			strPSResults = objExec.StdOut.ReadAll
			ip = ClientIP
			' Replace in output powershell 
			strPSResults = Replace(strPSResults, chr(13), ",",1,10000)
			strPSResults = Replace(strPSResults, chr(10), "",1,10000)
			
			
			If len(strPSResults) - len(replace(strPSResults, ",", "")) > 2000  then  ' Alert max 2.000 ips per rule
				EventLog.Write ("**** ATTENTION RULE BAN_IP 90%  ****")	     		 ' Write in log file
				EmailAlert() 													     ' Send email Alert max 2.000 ips per rule
			End If 

			' Add detected ip to output powershell
			ip = strPSResults + ip
			' Send old ip's and new ip to Firewall Rule
			Set objExec = objShell.Exec("powershell -windowstyle hidden -command Set-NetFirewallRule -DisplayName Ban_IP" & Month(Date()) & Year(Date()) & " -RemoteAddress"&" "&ip)
			' End Add to firewall
			Set objShell = Nothing
			Set objExec = Nothing
			
		End If
			Result.Value = 0
	End If
End Sub

Public Function EmailAlert() ' Send email Alert
	dim MessageRecipientName, MessageRecipientAddress, MessageSubject
	dim oApp, sBackupLog, oMessage
	Set oApp = CreateObject("hMailServer.Application")
		MessageRecipientName = "MAIL SERVER"  'CHANGE ME
		MessageRecipientAddress = "recipient@address.com"  'CHANGE ME
		MessageSubject = "ATTENTION RULE BAN_IP 90%" & Month(Date()) & Year(Date())& "."
		Call oApp.Authenticate("useradmin", "password")
		Set oMessage = CreateObject("hMailServer.Message")
		oMessage.From = "hMailServer" & "<recipient@address.com>"
		oMessage.FromAddress = "from@addresses.com"
		oMessage.Subject = MessageSubject
		oMessage.AddRecipient MessageRecipientName, MessageRecipientAddress
		oMessage.Body = "ATTENTION RULE BAN_IP 90% ." & vbNewLine & vbNewLine & sBackupLog			
		oMessage.Save
	Set oApp = Nothing
End Function

Public Function CheckAbuseIPDBConfidence(IPAddress) 'Check % ip in AbuseIPDB
	CheckAbuseIPDBConfidence = "0"
	Set objXMLHTTP = CreateObject("msxml2.xmlhttp.6.0")
		objXMLHTTP.Open "GET", "https://www.abuseipdb.com/check/" & IPAddress, False
		objXMLHTTP.Send ""
		ResponseText = objXMLHTTP.responseText
		ResponseArray = Split(ResponseText, VbLf)
		For Each ResponseLine in ResponseArray
			If Left(ResponseLine, 6) = "<span>" And Right(ResponseLine, 8) = "%</span>" Then
				CheckAbuseIPDBConfidence = Mid(ResponseLine,7, Len(ResponseLine)-14)
				Exit For
			End If
		Next	
	Set objXMLHTTP = Nothing
End Function	
Production 5.6.8-B2437.20_OpenSSL_1.0.2s W.Server 2016 Datace [2x Intel Xeon E5-2660 8GB RAM]
Staging 5.7-B2490 W.Server 2008 R2 Stand [Intel Pentium 4 4GB RAM]

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-20 15:41

With respect to the IDS code I posted earlier. I have reduced the script footprint in hMailserver from previously quoted 241 lines of active code to 55 lines of code. Plus it's no longer using the AODB.Connection and all the extra API calls - so all in all it should speed things up with a factor 500 (or something to that effect :wink: ).

I use AutoBan in my script but it could just as well be code to add IP Addresses to a firewall.

The "handler" part is not yet finished, but from hMailServers perspective - the "handler" is irellevant wrt. performance as it is running outside hMailServer.
As long as the "handler" code can access the database (socket or IP), it can be written in whatever programming language you prefer. :idea: :wink:

Actually, if you use IPTables on a 'Nix Box, you can run the "handler" directly on the 'Nix Box and access the database across the LAN. 8)

*** NEW ***

Code: Select all

'******************************************************************************************************************************
'********** hMailServer IDS Client Code (MySQL)                                                                      **********
'******************************************************************************************************************************

Private Const idsTable = "hm_ids2"

'   DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Port=3306;Database=%idsdb%;Uid=%idsuid%;Pwd=%idspwd%;Option=3;
'
'   Table:   CREATE TABLE %idsTable% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   port      INTEGER,
'                   hits      INTEGER);

Function idsAddIP(sIPAddress, iPort)
   Dim strSQL, oDB : Set oDB = GetDatabaseObject
   strSQL = "INSERT IGNORE INTO " & idsTable & " (timestamp,ipaddress,port,hits) VALUES (NOW(),'" & sIPAddress & "'," & iPort & ",0);"
   Call oDB.ExecuteSQL(strSQL)
   strSQL = "UPDATE " & idsTable & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
   Call oDB.ExecuteSQL(strSQL)
End Function

Function idsDelIP(sIPAddress)
   Dim strSQL, oDB : Set oDB = GetDatabaseObject
   strSQL = "DELETE FROM " & idsTable & " WHERE ipaddress = '" & sIPAddress & "';"
   Call oDB.ExecuteSQL(strSQL)
End Function

'******************************************************************************************************************************
'********** hMailServer Triggers                                                                                     **********
'******************************************************************************************************************************

Sub OnClientConnect(oClient)
   Dim strPort

   '   Only allow non-SMTP connect from "Rigsfællesskabet"/"Naalagaaffeqatigiit"/"Ríkisfelagsskapurin" = The Danish Realm.
   '   000 = N/A, 208 = Denmark, 304 = Greenland, 234 = Faroe Islands
   If (oClient.Port <> 25) Then
      If InStr("|208|304|234|", NerdLookup(oClient.IPAddress)) = 0 Then
         Call idsAddIP(oClient.IPAddress, oClient.Port)
         Result.Value = 1
         Exit Sub
      End If
   End If

   '   Only test SMTP traffic
   If InStr("|25|587|465|", oClient.Port) > 0 Then
      Call idsAddIP(oClient.IPAddress, 0)
   End If
End Sub

Sub OnAcceptMessage(oClient, oMessage)
      Call idsDelIP(oClient.IPAddress)
End Sub
*** OLD ***

Code: Select all

'******************************************************************************************************************************
'********** hMailServer IDS Code (MySQL)                                                                             **********
'******************************************************************************************************************************

Private Const idsDBDrv = "DRIVER={MySQL ODBC 5.3 Unicode Driver};Database=#DB#;Uid=#UID#;Pwd=#PWD#;Option=3;"
Private Const idsTab01 = "hm_ids"
Private Const idsHit01 = 3
Private Const idsMins  = 120
Private Const idsTab02 = "hm_portmon"
Private Const idsHit02 = 5

'   DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Port=3306;Database=#DB#;Uid=#UID#;Pwd=#PWD#;Option=3;

'   Table:   CREATE TABLE %ids% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   hits      INTEGER);"

'   Table:   CREATE TABLE %portmon% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   port      INTEGER,
'                   hits      INTEGER);"

Function idsDelete(sIPAddress)
   Dim oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsDelete - ERROR: Could not connect" )
      Exit Function
   End If
   oConn.Execute "DELETE FROM " & idsTab01 & " WHERE ipaddress = '" & sIPAddress & "';"
   oConn.Close
End Function

Function idsCheck(sIPAddress) : idsCheck = False
   Dim oRecord, oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsCheck - ERROR: Could not connect" )
      Exit Function
   End If
   On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTab01 & " WHERE ipaddress='" & sIPAddress & "';")
   On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "idsCheck - ERROR: Table " & idsTab01 & " does not exist!" )
      Exit Function
   End If
   If oRecord.BOF And oRecord.EOF Then '   IPAddress is NEW!
      oConn.Execute "INSERT IGNORE INTO " & idsTab01 & " (timestamp,ipaddress,hits) VALUES (NOW(),'" & sIPAddress & "',0);"
      oConn.Execute "UPDATE " & idsTab01 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
   Else '   In case of more than one record, unlikely since "ipaddress" have a UNIQUE constraint.
      While Not oRecord.EOF
         idsCheck = (oRecord("hits") >= idsHit01)
         If (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then '   IPAddress is known - but too old.
            oConn.Execute "UPDATE " & idsTab01 & " SET hits=1,timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         Else '   IPAddress is known - bump counter.
            oConn.Execute "UPDATE " & idsTab01 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         End If
         oRecord.MoveNext
      Wend
   End If
   oRecord.Close
   oConn.Close
End Function

Function idsPortMon(sIPAddress, iPort) : idsPortMon = False
   Dim oRecord, oConn : Set oConn = CreateObject("ADODB.Connection")
   oConn.Open idsDBDrv
   If oConn.State <> 1 Then
      EventLog.Write( "idsPortMon - ERROR: Could not connect" )
      Exit Function
   End If
   On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTab02 & " WHERE ipaddress='" & sIPAddress & "';")
   On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "idsPortMon - ERROR: Table " & idsTab02 & " does not exist!" )
      Exit Function
   End If
   If oRecord.BOF And oRecord.EOF Then '   IPAddress is NEW!
      oConn.Execute "INSERT IGNORE INTO " & idsTab02 & " (timestamp,ipaddress,port,hits) VALUES (NOW(),'" & sIPAddress & "'," & iPort & ",0);"
      oConn.Execute "UPDATE " & idsTab02 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
   Else '   IPAddress is known - bump counter.
      While Not oRecord.EOF
         idsPortMon = (oRecord("hits") >= idsHit02)
         oConn.Execute "UPDATE " & idsTab02 & " SET hits=(hits+1),timestamp=NOW() WHERE IPAddress='" & sIPAddress & "';"
         oRecord.MoveNext
      Wend
   End If
   oRecord.Close
   oConn.Close
End Function

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function Wait(sec)
   With CreateObject("WScript.Shell")
      .Run "timeout /T " & Int(sec), 0, True
'     .Run "sleep -m " & Int(sec * 1000), 0, True
'     .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
   End With
End Function

Function LockFile(strPath)
   Const Append = 8
   Const Unicode = -1
   With CreateObject("Scripting.FileSystemObject")
      Dim oFile, i
      For i = 0 To 30
         On Error Resume Next
         Set oFile = .OpenTextFile(strPath, Append, True, Unicode)
         If Not (Err.Number = 70) Then
            Set LockFile = oFile
            On Error Goto 0
            Exit For
         End If
         On Error Goto 0
         Wait(1)
      Next
   End With
   If (Err.Number = 70) Then
      EventLog.Write( "ERROR: EventHandlers.vbs" )
      EventLog.Write( "File " & strPath & " is locked and timeout was exceeded." )
      Err.Clear
   ElseIf (Err.Number <> 0) Then
      EventLog.Write( "ERROR: EventHandlers.vbs : Function LockFile" )
      EventLog.Write( "Error       : " & Err.Number )
      EventLog.Write( "Error (hex) : 0x" & Hex(Err.Number) )
      EventLog.Write( "Source      : " & Err.Source )
      EventLog.Write( "Description : " & Err.Description )
      Err.Clear
   End If
End Function

'   System Scripting Runtime COM object ("SScripting.IPNetwork")
'   http://www.netal.com/ssr.htm
'   Binary -> http://www.netal.com/software/ssr15.zip
'   http://countries.nerd.dk/isolist.txt

Function NerdLookup(strIP)
   Dim a
   a = Split(strIP, ".")
   With CreateObject("SScripting.IPNetwork")
      strIP = .DNSLookup(a(3) & "." & a(2) & "." & a(1) & "." & a(0) & ".zz.countries.nerd.dk")
   End With
   If Left(strIP, 3) <> "127" Then
      NerdLookup = "000"
   Else
      a = Split(strIP, ".")
      NerdLookup = Right("00" & CStr(a(2)*256 + a(3)), 3)
   End If
End Function

Function AutoBan(sIPAddress, sReason, iDuration, sType) : AutoBan = False
   '
   '   sType can be one of the following;
   '   "yyyy" Year, "m" Month, "d" Day, "h" Hour, "n" Minute, "s" Second
   '
   Dim oApp : Set oApp = CreateObject("hMailServer.Application")
   Call oApp.Authenticate(ADMIN, PASSWORD)
   With LockFile("c:\hmailserver\temp\autoban.lck")
      On Error Resume Next
      oApp.Settings.SecurityRanges.Refresh
      If (oApp.Settings.SecurityRanges.ItemByName("(" & sReason & ") " & sIPAddress) Is Nothing) Then
         With oApp.Settings.SecurityRanges.Add
            .Name = "(" & sReason & ") " & sIPAddress
            .LowerIP = sIPAddress
            .UpperIP = sIPAddress
            .Priority = 20
            .Expires = True
            .ExpiresTime = DateAdd(sType, iDuration, Now())
            .Save
         End With
         AutoBan = True
      End If
      oApp.Settings.SecurityRanges.Refresh
      On Error Goto 0
      .Close
   End With
End Function

'******************************************************************************************************************************
'********** hMailServer Triggers                                                                                     **********
'******************************************************************************************************************************

Sub OnClientConnect(oClient)
   Dim strPort

   '   Only allow non-SMTP connect from "Rigsfællesskabet"/"Naalagaaffeqatigiit"/"Ríkisfelagsskapurin" = The Danish Realm.
   '   000 = N/A, 208 = Denmark, 304 = Greenland, 234 = Faroe Islands
   If (oClient.Port <> 25) Then
      If InStr("|208|304|234|", NerdLookup(oClient.IPAddress)) = 0 Then
         If idsPortMon(oClient.IPAddress, oClient.Port) Then
            Result.Value = 1
            strPort = Trim(Mid("SMTP IMAP SMTPSSUBM IMAPS", InStr("25   143  465  587  993  ", oClient.Port), 5))
            If AutoBan(oClient.IPAddress, "PORTBLOCK - " & strPort, 1, "d") Then _
               EventLog.Write( "AutoBan(" & oClient.IPAddress & ", PORTBLOCK - " & strPort & ", 1, d)" )
            Exit Sub
         Else
            Result.Value = 1
            Exit Sub
         End If
      End If
   End If

   '   Only test SMTP traffic
   If InStr("|25|587|465|", oClient.Port) > 0 Then
      If idsCheck(oClient.IPAddress) Then
         Result.Value = 1
         If AutoBan(oClient.IPAddress, "IDS", 7, "d") Then _
            EventLog.Write( "AutoBan(" & oClient.IPAddress & ", IDS, 7, d)" )
         Exit Sub
      End If
   End If
End Sub


Sub OnAcceptMessage(oClient, oMessage)

   '   Cleanup IDS registry
   idsDelete(oClient.IPAddress)

End Sub
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-20 18:42

My "handler" ... It's running alpha test right now. Nothing has blown up yet, so we'll see ... :mrgreen:

handler.vbs runs every 5 minutes.

You can regard this whole excercise a Proof of Concept on how to offload tasks from hMailServer execution.

Code: Select all

Option Explicit

'******************************************************************************************************************************
'********** Settings                                                                                                 **********
'******************************************************************************************************************************

'   COM authentication
Private Const ADMIN = "Administrator"
Private Const PASSWORD = "SECRETPASSWORDDONOTFORGETTOCHANGE"

'******************************************************************************************************************************
'********** hMailServer IDS Handler Code (MySQL)                                                                     **********
'******************************************************************************************************************************

Private Const idsDBDrv = "DRIVER={MySQL ODBC 5.3 Unicode Driver};Database=#DB#;Uid=#UID#;Pwd=#PWD#;Option=3;"
Private Const idsTable = "hm_ids2"
Private Const idsHit01 = 3
Private Const idsHit02 = 5
Private Const idsMins  = 120

'   DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Port=3306;Database=%idsdb%;Uid=%idsuid%;Pwd=%idspwd%;Option=3;
'
'   Table:   CREATE TABLE %idsTable% (
'                   id        INTEGER       PRIMARY KEY AUTO_INCREMENT,
'                   timestamp DATETIME,
'                   ipaddress VARCHAR (192) UNIQUE,
'                   port      INTEGER,
'                   hits      INTEGER);

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function Wait(sec)
   With CreateObject("WScript.Shell")
      .Run "timeout /T " & Int(sec), 0, True
'     .Run "sleep -m " & Int(sec * 1000), 0, True
'     .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
   End With
End Function

Function LockFile(strPath)
   Const Append = 8
   Const Unicode = -1
   With CreateObject("Scripting.FileSystemObject")
      Dim oFile, i
      For i = 0 To 30
         On Error Resume Next
         Set oFile = .OpenTextFile(strPath, Append, True, Unicode)
         If Not (Err.Number = 70) Then
            Set LockFile = oFile
            On Error Goto 0
            Exit For
         End If
         On Error Goto 0
         Wait(1)
      Next
   End With
   If (Err.Number = 70) Then
      EventLog.Write( "ERROR: BanJob.vbs" )
      EventLog.Write( "File " & strPath & " is locked and timeout was exceeded." )
      Err.Clear
   ElseIf (Err.Number <> 0) Then
      EventLog.Write( "ERROR: BanJob.vbs : Function LockFile" )
      EventLog.Write( "Error       : " & Err.Number )
      EventLog.Write( "Error (hex) : 0x" & Hex(Err.Number) )
      EventLog.Write( "Source      : " & Err.Source )
      EventLog.Write( "Description : " & Err.Description )
      Err.Clear
   End If
End Function

Function AutoBan(sIPAddress, sReason, iDuration, sType) : AutoBan = False
   '
   '   sType can be one of the following;
   '   "yyyy" Year, "m" Month, "d" Day, "h" Hour, "n" Minute, "s" Second
   '
'*    Dim oApp : Set oApp = CreateObject("hMailServer.Application")
'*    Call oApp.Authenticate(ADMIN, PASSWORD)
   With LockFile("c:\hmailserver\temp\autoban.lck")
      On Error Resume Next
      oApp.Settings.SecurityRanges.Refresh
      If (oApp.Settings.SecurityRanges.ItemByName("(" & sReason & ") " & sIPAddress) Is Nothing) Then
         With oApp.Settings.SecurityRanges.Add
            .Name = "(" & sReason & ") " & sIPAddress
            .LowerIP = sIPAddress
            .UpperIP = sIPAddress
            .Priority = 20
            .Expires = True
            .ExpiresTime = DateAdd(sType, iDuration, Now())
            .Save
         End With
         AutoBan = True
      End If
      oApp.Settings.SecurityRanges.Refresh
      On Error Goto 0
      .Close
   End With
End Function

'******************************************************************************************************************************
'********** Code                                                                                                     **********
'******************************************************************************************************************************

Dim oApp : Set oApp = CreateObject("hMailServer.Application")
Call oApp.Authenticate(ADMIN, PASSWORD)
Dim EventLog : Set EventLog = CreateObject("hMailServer.EventLog")
Dim strPort, Done

Dim oRecord, oConn : Set oConn = CreateObject("ADODB.Connection")
oConn.Open idsDBDrv
If oConn.State <> 1 Then
   EventLog.Write( "Handler - ERROR: Could not connect to database" )
   Quit 1
End If

Done = False
Do Until Done
   ' On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTable & " WHERE PORT = 0 AND HITS >= '" & idsHit01 & "';")
   ' On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "Handler - ERROR: Table " & idsTable & " does not exist!" )
      WScript.Quit 1
   End If
   If oRecord.BOF And oRecord.EOF Then
      Exit Do
   Else
      While Not oRecord.EOF
         If (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then
            oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
         Else
            If AutoBan(oRecord("ipaddress"), "IDS", 7, "d") Then 
               EventLog.Write( "AutoBan(" & oRecord("ipaddress") & ", IDS, 7, d)" )
            End If
         End If
         oRecord.MoveNext
      Wend
   End If
   Done = True
Loop

Done = False
Do Until Done
   ' On Error Resume Next
   Set oRecord = oConn.Execute("SELECT * FROM " & idsTable & " WHERE PORT > 0 AND HITS >= '" & idsHit02 & "';")
   ' On Error Goto 0
   If Err.Number <> 0 Then
      EventLog.Write( "Handler - ERROR: Table " & idsTable & " does not exist!" )
      WScript.Quit 1
   End If
   If oRecord.BOF And oRecord.EOF Then
      Exit Do
   Else
      While Not oRecord.EOF
         If (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then
            oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
         Else
            strPort = Trim(Mid("SMTP IMAP SMTPSSUBM IMAPS", InStr("25   143  465  587  993  ", oRecord("port")), 5))
            If AutoBan(oRecord("ipaddress"), "PORTBLOCK - " & strPort, 1, "d") Then 
               EventLog.Write( "AutoBan(" & oRecord("ipaddress") & ", PORTBLOCK - " & strPort & ", 1, d)" )
            End If
         End If
         oRecord.MoveNext
      Wend
   End If
   Done = True
Loop

WScript.Quit 0
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

tunis
Normal user
Normal user
Posts: 226
Joined: 2015-01-05 20:22
Location: Sweden

Re: Check incoming connections with AbuseIPDB

Post by tunis » 2018-12-21 15:18

Should not the database record always be removed if it's banned or old.

Code: Select all

     While Not oRecord.EOF
         If Not (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then
            If AutoBan(oRecord("ipaddress"), "IDS", 7, "d") Then 
               EventLog.Write( "AutoBan(" & oRecord("ipaddress") & ", IDS, 7, d)" )
            End If
         End If
         oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
         oRecord.MoveNext
      Wend
or

Code: Select all

      While Not oRecord.EOF
         If (DateDiff("n", oRecord("timestamp"), Now()) > idsMins) Then
            oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
         Else
            If AutoBan(oRecord("ipaddress"), "IDS", 7, "d") Then 
               EventLog.Write( "AutoBan(" & oRecord("ipaddress") & ", IDS, 7, d)" )
               oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
            End If
         End If
         oRecord.MoveNext
      Wend
HMS 5.6.8 B2437.17 on Windows Server 2019 Core VM.
HMS 5.6.8 B2451.21 on Windows Server 2016 Core VM.
HMS 5.6.7 B2425.16 on Windows Server 2012 R2 Core VM.

User avatar
SorenR
Senior user
Senior user
Posts: 3228
Joined: 2006-08-21 15:38
Location: Denmark

Re: Check incoming connections with AbuseIPDB

Post by SorenR » 2018-12-21 17:37

Good point - I actually did that - after updating the forum :roll:

Anyways, a while back I changed the AutoBan() function so it's not really a problem - it will catch it and ignore it.

Code: Select all

      While Not oRecord.EOF
         ' EventLog.Write( "Wohoo... IPAddress: " & oRecord("ipaddress") & " Port: " & oRecord("port") & " Hits: " & oRecord("hits") )
         If (DateDiff("n", oRecord("timestamp"), Now()) <= idsMins) Then
            If AutoBan(oRecord("ipaddress"), "IDS", 7, "d") Then 
               EventLog.Write( "AutoBan(" & oRecord("ipaddress") & ", IDS, 7, d)" )
            End If
         End If
         oConn.Execute "DELETE FROM " & idsTable & " WHERE IPAddress='" & oRecord("ipaddress") & "';"
         oRecord.MoveNext
      Wend
I have a (another) job that runs every 30 minutes where this is included;

Code: Select all

oConn.Execute "DELETE FROM " & idsTable & " WHERE PORT = 0 AND DATE_ADD(timestamp, INTERVAL 12 HOUR) < NOW();"
oConn.Execute "DELETE FROM " & idsTable & " WHERE PORT > 0 AND DATE_ADD(timestamp, INTERVAL 24 HOUR) < NOW();"
tunis wrote:
2018-12-21 15:18
Should not the database record always be removed if it's banned or old.
SørenR.

“With age comes wisdom, but sometimes age comes alone.”
- Oscar Wilde

Post Reply