|
The other option to
create contacts in the AD is via an input file, by default the
SMTPSPAMFilter.vbs
script logs information to
NewSPAMHosts.log
that can be used to create contacts with the same properties as those
created via the folder method above.
First we need to bind
to the file that contains the list of host. Then we will start a Do
While loop that will continue until each line of the text file has been
read in. With each line we parse the data, which should be separated
with tabs,
Chr(9), to get the sending host IP,
claimed DNS host name, and the message header. The last two fields
aren?t required but will be used if they exist. We then get the class C
address of the sending host by calling the custom
GetClassC
function which replaces the last IP bit with a 0, zero.
Then we try to bind
to the contact in the AD, since there is no point in trying to create a
new contact and looking up information on the IP if a contact already
exists. First the script attempts to bind to a contact with the
cn
of the sending host IP. If this fails it then tries the class C
address. If both fails then the rest of the script will continue,
otherwise the next line is read in. The
80072030
is the string and hex equivalent of the integer error code for ?object
not found?.
The first check is to see if the sending
IP has been blacklisted. If it hasn?t been blacklisted we then attempt
to look up equivalent DNS name with the
NSLookUp
function. If the DNS lookup fails it is assumed the host should be
blocked and the variables are set to match the format used in the Sub
above. Otherwise, we call the
CheckDomainName
function to return the
HostDNS
name,
HostIP to be blocked, and
sn
to be used for the contact.
Next we reformat the header so each piece
of header data will be on a different line by using the
Replace function. This is needed because
SMTPSPAMFilter.vbs
puts all the header information on
one line separated by ?^^^?. We then check to see if
HostDNS
is blank, if it is blank the script assume the host is valid and a
contact shouldn?t be created for it. If the
HostDNS
does contain data we then check to see if the contact should be created
using the class C address, if so the
HostIP
is changed to a class C address. Then
HostDNS
is checked to see if it contains ?Unknown?, which indicates the host was
not a dynamic or know valid host, and appends the claimed DNS name to
HostDNS.
Last
CreateContact
is called with the variable needed to set the fields on the contact in the
same way as the
ReadInItems
sub. After the contact is create the loop continues to the next line in
the input file
Sub LoadHosts (SpamHosts,objSpamContactsOU)
givenName = "File"
? Used when creating
the contact
Set objInputFile = objFS.OpenTextFile (SpamHosts, 1, True)
Do While ObjInputFile.AtEndOfStream <> True
ReadText = Trim(ObjInputFile.ReadLine)
RealServerIP = GetField(ReadText,Chr(9))
ClaimedHostDNS = GetField(ExtraData,Chr(9))
MsgHeader = GetField(ExtraData,Chr(9))
SendingHostClassC = GetClassC(RealServerIP)
SpamContactPath = "LDAP://" & TargetDC & "/" & "cn=" &
RealServerIP & "," & _
SpamContactsOU & "," & DomainDN
On Error Resume Next
Set objSpamContact = GetObject (SpamContactPath)
' If
the error was object not found try to bind to the contact with the
'
class C address
If CStr(Hex(Err.Number)) = "80072030" Then
SpamContactPath = "LDAP://" & TargetDC & "/" &
"cn=" & SendingHostClassC & _
"," & SpamContactsOU &
"," & DomainDN
Set objSpamContact = GetObject (SpamContactPath)
End If
If CStr(Hex(Err.Number)) = "80072030" Then
? If still not found
check out the host
On Error GoTo 0
If BlackListed (RealServerIP,BlackListedBy) Then
HostDNS = "Blacklisted by [" &
BlackListedBy & "] Claimed: " & ClaimedHostDNS
sn = "Blacklisted"
Else
RealDNS = NSLookUp(RealServerIP,"Name:")
? Assume the host is a
spamer and set the fields used by the contacts
If RealDNS = "Invalid" Then
HostDNS = ClaimedHostDNS
RealDNS = "Failed
NSLookup"
sn = "Failed NSLookup"
HostDNS = "Failed
NSLookup, claimed: [" & ClaimedHostDNS & "]"
Else
'
Returns blank data if host is well known host or non-dynamic part
' of the hostif it is a dial-up host
HostDNS = CheckDomainName
(RealServerIP,HostIP,RealDNS,sn)
End If
End If
' Check for
blacklisting
' ^^^ is used as a
seperator in NewSPAMHosts.log for the message header
If InStr(MsgHeader,"^^^") > 0 Then
MsgHeader = Replace(MsgHeader,"^^^",VbCrLf)
End If
If HostDNS <> "" Then
If UseClassC Then HostIP =
SendingHostClassC End If
If InStr(HostDNS,"Unknown ") > 0 Then
HostDNS = HostDNS & " ,
claimed: " & ClaimedHostDNS
End If
CreateContact
(objSpamContactsOU,HostIP,RealServerIP,HostDNS,MsgHeader,givenName,sn)
End If
End If
' Contact not found
error
Loop
End Sub
The sub below creates
the contacts in the AD that
SMTPSPAMFilter.vbs
checks. Both the
LoadHosts
and
ReadInItems
Subs call this Sub to
create the contacts in the AD and pass it the required and optional
fields. The
description
is based on how the host was determined to be a spamer. Below is list
of the possible descriptions:
Blacklisted: ?Blacklisted by [DNS
name of blacklist server], claimed [host
name from header]?
Dynamic: ?Dynamic Host: [Real
DNS name acquired based on an NSLookup]?
Failed NSLookup: ?Failed NSLookup, claimed
[host name from header]?
Unknown Host: ?Unknown Host: [RealDNS],
claimed [host name from header]?
Bad Domain: ?Known Spamer: [RealDNS],
claimed [host name from header]?
- This example isn?t covered
in this article but is supported by the attached script
As for the properties
displayname
should always be the real IP address of the sending server,
givenName
will be either ?Folder? or ?File? based on which input method was used
to create the contact,
sn
will contain ?Blacklisted?, ?Dynamic?, ?Failed NSLookup?, "Unknown
Host", or ?Known
Spamer?. Last
info
will contain the message header of the message that caused the contact
to be created. This field should contain all of the To, From, Time,
Subject, and other header information which will be very useful when
trying to see why a host was flagged as a spamer.
-
Sub CreateContact (objOU,cn,displayName,description,info,givenName,sn)
Dim objContact
Set objContact =
objOU.Create("contact", "CN=" & cn)
objContact.Put
"description", description
objContact.Put "displayname",
displayName
objContact.Put "givenName",
givenName
objContact.Put "sn", sn
objContact.Put "info", info
objContact.SetInfo
Set objContact = Nothing
End Sub
GetField
This function will return the data to the
left of the delimiter it is passed, for this script
Chr(9)
is used. It also returns the remaining data in the
ExtraData
variable. This variable should be declared at the top of the script so
it is available, global, to all Functions and Subs.
-
Function GetField (Data,Delimiter)
If InStr(Data,Delimiter) = 0 Then
GetField = Data
ExtraData = ""
Exit Function
End If
GetField =
Left(Data,InStr(Data,Delimiter)-1)
ExtraData =
Right(Data,Len(Data)-InStr(Data,Delimiter)-Len(Delimiter)+1)
End Function
CheckDomainName
This is the function
that carries out multiple checks, and calls several other functions, to
see if the host IP is a valid host and sets the variables that are used
to populate the contact in the AD. It will return the class C address
and non-dynamic part of the DNS name if a message is from a
dynamic\dial-up host, like 123-56-67-8.dial-up.msn.net. This way all
mail from that dynamic class C address block will be blocked
from sending future e-mails to your server. It will also check to see
if the domain name is in the valid domain list, which is set at the top
of the script with the
Const
ValidDomains
= statement. If the host is valid
and not-dynamic then
CheckDomainName returns blank data
and sets
ServerIP to nothing.
The function first check to make sure it
was passed valid data in
RealDNS.
Then it gets the non-dynamic part of the DNS name by calling the
NonDynamicPart
function. Next, it then checks to see if the sending host is a dynamic
host by comparing the real DNS name and
non-dynamic part of the DNS name. If the host is dynamic then
ServerIP
is set to the class C address, so all
e-mail sent from this address block will be blocked, since the host is
part of a dynamic pool.
Next we check to see if the last part of
the DNS name is in the valid domain list. If so we need to carry out
several checks to determine if we should block traffic from it. First
we see if the "valid" host isn?t dynamic by comparing the real DNS name and the
non-dynamic DNS name. If they are found to be the same, like
mail.msn.net, both
CheckDomainName
and
ServerIP are sent to blank, which
will prevent a contact from being created and mail from being blocked
from this host. If they aren?t the same it must mean that the real DNS
name had part of the sending servers IP address in it, like
1-2-3-4.dial-up.msn.net. If so we then check to see if there is
something in front of the valid part of the DNS name, in the previous
example ?dial-up? is in front of the valid domain ?msn.net.? If there
is something between the dynamic parts and known DNS part the script
will assume that it should block all mail from the class C address of
the sending IP. This is because the I assumes that dial-up, DSL, cable users, etc
will be connecting to a different IP subnet then that companies outgoing mail
servers. This should be a pretty valid assumption for the larger ISPs
since they normally have a dedicated class C just for their non-dynamic
host, like mail servers.
Note: If you have users that connect via
SMTP\POP3 to your Exchange servers from the outside\internet they will be prevented from sending
e-mail if they are dialing into an ISP that assigns IPs in the same range of
a block class C address. This is because messages sent by users
via a SMTP client will show-up as coming from their dialed up IP address. To prevent
this from happening you might want to modify the section talked about
above to not block any data from known hosts by adding
ServerIP = ??
and changing
CheckDomainName = from
"Known Dynamic
Host: [" & NonDynamicRealDNS & "]"
to
??.
If the non-dynamic part of the DNS name is
found to be the same as a valid domain name, like where the real DNS
name is 123-56-67-8. msn.net, then
CheckDomainName
and
ServerIP are sent to blank. Since
there is a good chance that blocking this class C address will block all
e-mail from this domain.
Last if the DNS name was not in the valid
domain list it is assumed the host is a spamer and the variables that
are used to populate the contact are sent.
-
Function CheckDomainName (RealServerIP,ServerIP,RealDNS,CheckStatus)
If RealDNS = "" or RealDNS =
"Invalid" Then Exit Function End If
' Will strip out the IP address from a host
name
' Example: 1-2-3-4.dial-up.msn.net will become dial-up.msn.net
NonDynamicRealDNS =
NonDynamicPart(RealDNS,RealServerIP)
If RealDNS <> NonDynamicRealDNS Then
' If message was sent from a dynamic
host then block by the Class C address
CheckStatus = "Dynamic Host"
CheckDomainName = "Unknown Dynamic
Host: [" & NonDynamicRealDNS & "]"
ServerIP = GetClassC(ServerIP)
End If
If
InStr(LCase(ValidDomains),LCase(GetPartialDomain (RealDNS,2))) > 0
Then
If NonDynamicRealDNS = RealDNS Then
' Example mail.msn.com, site won't be blocked
CheckDomainName = ""
ServerIP = ""
Else
'
Dynamic host like 1-2-3-4.msn.net or 1-2-3-4.dial-up.msn.net
' Makes sure the non-dynamic part isn't a
valid domain name, like 1-2-3-4.msn.net
If
InStr(LCase(ValidDomains),LCase(NonDynamicRealDNS)) = 0 Then
' If RealDNS = 1-2-3-4.dial-up.msn.net this
would return dial-up.msn.net
CheckDomainName = "Known Dynamic
Host: [" & NonDynamicRealDNS & "]"
CheckStatus = "Dynamic host"
Else
' Non-dynamic part is in the
list of valid domains so don't filter it
' Example: 1-2-3-4.msn.net
would equal msn.net
CheckDomainName = ""
ServerIP = ""
End If ' NonDynamicDNS in valid
domain list
End If ' NonDynamicDNS is same as
RealDNS
Else
' The host name
wasn't in the valid domain name list and isn't blacklisted
' If CheckStatus hasn't been set yet then the
host must be a non-dynamic unknown host
If CheckStatus = "" Then
CheckStatus = "Unknown Host"
CheckDomainName = "Unknown Host: [" &
RealDNS & "]"
End If
End If
' RealDNS contains a valid
domain
End Function
|