Wednesday, July 19, 2017

TransportAgentFactory type must be the Microsoft .NET class type of the transport agent factory.

The error correct in two ways :)

1. Install last CU for Exchange
2. Close and open "Exchange Management Shell"

How to log the names and size of attachments in messages (Exchange 2013/2016)

I want to share with you "Exchange TransportAgent" which log the names and size of attachments.
I test this agent on Exchange 2013 CU17 (15.00.1320.004) and Exchange 2016 CU6 (15.01.1034.026).

Download "AttachmentLog TransportAgent for Exchange 2013 CU17"

Download "AttachmentLog TransportAgent for Exchange 2016 CU6"

The location of the folder with logs can be controlled from the file "AttachmentLog.Config.xml"

Example of install:

001
002
003
004
005
$EXDIR="C:\MyAgents\AttachmentLog"
Net Stop MSExchangeTransport
Install-TransportAgent -Name "MyAttachmentLog" -AssemblyPath $EXDIR\AttachmentLog.dll -TransportAgentFactory MyAttachmentLog.Exchange.Agents.AttachmentLog.AttachmentLogFactory
Enable-TransportAgent -Identity "MyAttachmentLog"
Net Start MSExchangeTransport

Example of uninstall:

001
002
Uninstall-TransportAgent -Name "MyAttachmentLog"
Restart-Service MSExchangeTransport

Check Exchange version:

001
Get-Command Exsetup.exe | ForEach{$_.FileVersionInfo}

Example of results:



Wednesday, July 5, 2017

How to parse Windows DNS debug logs with Logparser: create statistics

In this article I share a powershell script that will help to identify anomalies in your DNS. Script create TOP-30 Queries and TOP-30 Clients. With the help of MS Logparser you can very quickly check the debug log files of windows-dns.

Download powershell script

1. Enable DNS debug log on all dns-servers
- set limit for file size
- set same path


2. Install on the PC from which you run the script Logparser

3. For script you have to set
- servers
- domains
- homefolder
- files with dns debug logs
- email server (anonymous smtp)
- user email

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
# Set variables
$HomeFolder = "D:\Scripts"
cd $HomeFolder
$LogParser = "C:\Program Files (x86)\Log Parser 2.2\LogParser.exe"
$Servers = @("dc1.blogspot.com","dc2.blogspot.com","dc3.blogspot.com")

$msg = new-object Net.Mail.MailMessage
$msg.From = "myscript@blogspot.com"
$msg.To.add("i-evgeny@blogspot.com")
$msg.Subject = "DNS-query statistics"
$msg.IsBodyHTML = $true
$SMTPServer = "smtp.blogspot.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)

$LogTime = Get-Date -Format "yyyy-MM-dd_hh-mm-ss"
if (!(test-path "$HomeFolder\Logs")) {New-Item -ItemType directory -Path "$HomeFolder\Logs"}
$LogFile = $HomeFolder + "\Logs\DNSParser_"+$LogTime+".log"
$LogFile_top_domain = $HomeFolder + "\Logs\DNSParser_top_domain_" + $LogTime + ".log"
$LogFile_top_ip = $HomeFolder + "\Logs\DNSParser_top_ip_" + $LogTime + ".log"
$TempFile = $HomeFolder + "\DNSTemp.csv"
$DCs_str = ""
$i = 1
foreach ($d in $Servers) {
    if ($i -eq "1") {$DCs_str = "\\$($d)\c$\Scripts\Logs\Queries.log"
    } else {$DCs_str += ",\\$($d)\c$\Scripts\Logs\Queries.log"}
    $i++
}

# Logparser query: group by query, client ip

$query = """SELECT field8,CASE field16 WHEN NULL THEN field15 ELSE field16 END AS myquery INTO $($TempFile) FROM $DCs_str"""
$LogParserStr = "-i:TSV -iSeparator:space -nFields:16 -headerRow:OFF -nSkipLines:30 -o:csv " + $query
$LP = Start-Process -FilePath $LogParser -ArgumentList $LogParserStr -Wait -Passthru -NoNewWindow

Start-Sleep -s 15

$query_top_domain = """SELECT myquery, COUNT(myquery) INTO $LogFile_top_domain FROM $TempFile GROUP BY myquery ORDER BY COUNT(myquery) DESC"""
$LogParserStr = "-i:csv -o:csv " + $query_top_domain
$LP = Start-Process -FilePath $LogParser -ArgumentList $LogParserStr -Wait -Passthru -NoNewWindow

$query_top_ip = """SELECT Field8, COUNT(Field8) INTO $LogFile_top_ip FROM $TempFile GROUP BY field8 ORDER BY COUNT(field8) DESC"""
$LogParserStr = "-i:csv -o:csv " + $query_top_ip
$LP = Start-Process -FilePath $LogParser -ArgumentList $LogParserStr -Wait -Passthru -NoNewWindow

# Transformation query

$result_top_domain = import-csv $LogFile_top_domain
$good_result_top_domain = @()

for($i=0$i -le 29$i++) {
     $t=@()
     $good_name = $result_top_domain[$i].myquery -replace "\s" -replace "\(\d?\d\)","." -replace "^\." -replace "\.$"
     $t = new-object PSObject -Property @{
      Query = "$good_name";
      C = "$($result_top_domain[$i]."COUNT(ALL myquery)")"
     }
     $good_result_top_domain += $t
     $t=@()
}

# Create table for email

$msg.Body = "<html>
<body>TOP-30 Queries <br><br><table border=""0"" cellpadding=""3"" style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr bgcolor=""#dddddd"">
<td valign=""top""><b>Query</b></td>
<td valign=""top""><b>Count</b></td>
</tr>
<tr bgcolor=""#dddddd"">
<td valign=""top"">"


foreach ($g in $good_result_top_domain) {
    $msg.Body += "$($g.query)</td><td valign=""top"">$($g.c)</td></tr><tr bgcolor=""#dddddd""><td valign=""top"">"
}

$result_top_ip = import-csv $LogFile_top_ip

$msg.Body += "</td></tr></table><br>TOP-30 Clients <br><br><table border=""0"" cellpadding=""3"" style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr bgcolor=""#dddddd"">
<td valign=""top""><b>Clients</b></td>
<td valign=""top""><b>Count</b></td>
</tr>
<tr bgcolor=""#dddddd"">
<td valign=""top"">"


for($i=0$i -le 29$i++) {
     $msg.Body += "$($result_top_ip[$i].field8)</td><td valign=""top"">$($result_top_ip[$i]."COUNT(ALL Field8)")</td></tr><tr bgcolor=""#dddddd""><td valign=""top"">"
}
$msg.Body += "</td></tr></table></body></html>"

# Send statistics

$SMTPClient.Send($msg)

4. Schedule a task, runas account must have read permission for Debug files

Example of result:


Sunday, July 2, 2017

Quick start with PaloAlto active-active cluster and two ISP. Part2

In the first part we configured the cluster.
In the second part, we will configure two providers
Quick start :)
Case:
Active-Active cluster
Two ISP
Management IP 192.168.0.10/24
DNS IP 192.168.0.20, 192.168.0.30
Gateway 192.168.0.1
6 ethernet card (1 management, 1 local, 1 isp1, 1 isp2, 2 system replication)

1. Go to "Network – Virtual Routers – default – Static Routes". Create local and ISP


2. Go to "Network – Virtual Routers – default – Router Settings – ECMP" and enable "ECMP".
Commit config



3. Go to "Network – Interfaces". Check/assign a default virtual router for interfaces.


4. Go to "Policies - Security". Create a test access rule




5. Go to "Policies - NAT". Create nat-rules for two nodes


6. Let's check!

Tuesday, June 27, 2017

How to parse Windows DNS debug logs with Logparser for VIRUS (eg WannaCRY)

In this article I share a powershell script that will help to identify infected WannaCRY PCs and other botnet in your network. With the help of MS Logparser you can very quickly check the debug log files of windows-dns.

Download powershell script

1. At first enable DNS debug log on all dns-servers
- set limit for file size
- set same path (for script)


2. Install on the PC from which you run the script Logparser

3. For script you have to set
- servers
- domains
- homefolder
- file's path with dns debug logs
- email server (anonymous smtp)
- user email

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
# Set variables
$HomeFolder = "D:\Scripts"
cd $HomeFolder
if (!(test-path "$HomeFolder\Logs")) {New-Item -ItemType directory -Path "$HomeFolder\Logs"}
$LogParser = "C:\Program Files (x86)\Log Parser 2.2\LogParser.exe"

$Servers = @("dc1.blogspot.com","dc2.blogspot.com","dc3.blogspot.com")
$VirDomains = @("iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea","ifferfsodp9ifjaposdfjhgosurijfaewrwergwea","ayylmaoTJHSSTasdfasdfasdfasdfasdfasdfasdf","pingdavinci","wizardtesla","archimedus")

$msg = new-object Net.Mail.MailMessage
$msg.From = "myscript@blogspot.com"
$msg.To.add("i-evgeny@blogspot.com")
$msg.Subject = "Virus DNS Parser"
$SMTPServer = "smtp.blogspot.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
$LogTime = Get-Date -Format "yyyy-MM-dd_hh-mm-ss"
$LogFile = $HomeFolder + '\Logs\'+"parser_vir_"+$LogTime+".log"

# Logparser query
$VirDomains_str = ""
$i = 1
foreach ($v in $VirDomains) {
    if ($i -eq "1") {
    $VirDomains_str = "field15 LIKE '%$($v)%' OR field16 LIKE '%$($v)%'"
    } else {
    $VirDomains_str += " OR field15 LIKE '%$($v)%' OR field16 LIKE '%$($v)%'"
    }
    $i++
}

$DCs_str = ""
$i = 1
foreach ($d in $Servers) {
    if ($i -eq "1") {
    $DCs_str = "\\$($d)\c$\Scripts\Logs\Queries.log"
    } else {
    $DCs_str += ",\\$($d)\c$\Scripts\Logs\Queries.log"
    }
    $i++
}

$query = """SELECT * INTO $($LogFile) FROM $DCs_str WHERE $VirDomains_str"""
$LogParserStr = "-i:TSV -iSeparator:space -nFields:16 -headerRow:OFF -nSkipLines:30 -o:csv " + $query
$LP = Start-Process -FilePath $LogParser -ArgumentList $LogParserStr -Wait -Passthru -NoNewWindow
Start-Sleep -s 15
$Result = import-csv $LogFile

# Send alert
    if ($Result) {
        $vir_ip = $result | select field8 -Unique
        $msg.Body = "$($vir_ip.field8)"
        $att = new-object Net.Mail.Attachment($LogFile)
        $msg.Attachments.Add($att)
        $SMTPClient.Send($msg)
    }

4. Schedule a task (eg every 1 hour), runas account must have read permission for DNS Debug files

Quick start with PaloAlto active-active cluster and two ISP. Part1

In the first part, we will create a cluster.
Quick start :)
Case:
Active-Active cluster
Two ISP
Management IP 192.168.0.10/24
DNS IP 192.168.0.20, 192.168.0.30
Gateway 192.168.0.1
6 ethernet card (1 management, 1 local, 1 isp1, 1 isp2, 2 system replication)

1. Login to console, assign IP for manage, DNS. Default cred: admin/admin
Configure
set deviceconfig system ip-address 192.168.0.10 netmask 255.255.255.0 default-gateway 192.168.0.1 dns-setting servers primary 192.168.0.20
set deviceconfig system ip-address 192.168.0.10 netmask 255.255.255.0 default-gateway 192.168.0.1 dns-setting servers secondary 192.168.0.30
commit

Next, go to web-console https://192.168.0.10


2. Go to "Device – Licenses - Activate feature using authorization code" on web-console.
Open https://support.paloaltonetworks.com "ASSETS – VM-Series Auth-Codes – Register VM – lic-file", register and download license.


3. Install license


4. Install updates




5. Set strong password


6. Create cluster: Assign network interface type (You can check network by mac-address, show interface all), zone, virtual router
Ethernet1/1 – ISP1
Ethernet1/2 – ISP2
Ethernet1/3 – repl
Ethernet1/4 – local
Ethernet1/5 – repl



7. Go to "Device – High Availability - General" and create Active-Active Cluster:
Section "Setup": type second node's ip address;
Section "Control Link (HA1)": choose "managment" interface;
Section "Data Link": choose first replication interface - Ethernet1/3, assign ip address.
Commit Config and repeat steps on second node.


8. Go to "Device – High Availability - Active/Active Config". Choose second replication interface - Ethernet1/5 for session replications. Assign virtual ip addresses(two ISP and local). Commit config.


9. Go to "Dashboard" and add "Widgets – System – High Availability". Check cluster.


10. Let's check!

Friday, February 24, 2017

An example of creating "personal blacklist" function in the Asterisk (Elastix)

In this example, we add a function "personal blacklist" in /etc/asterisk/extensions_custom.conf  for followme calls (in the previous post, we added a feature "out of office")

Example:
Users phones: 10XXX

Then users can use this function from phones:
*13 - add
*14 - remove

1. Add to /etc/asterisk/extensions_custom.conf enable and disable blocks

[from-internal-custom]

;personal blacklist
exten => *13,1,Goto(personal-blacklist-add,s,1)
exten => *14,1,Goto(personal-blacklist-remove,s,1)

2. Add to /etc/asterisk/extensions_custom.conf check blocks in Followme


[personal-blacklist-add]

exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Set(NumLoops=0)
exten => s,n(start),Playback(enter-num-blacklist)
exten => s,n,Set(TIMEOUT(digit)=5)
exten => s,n,Set(TIMEOUT(response)=60)
exten => s,n,Read(blacknr,then-press-pound,,,,)
exten => s,n,SayDigits(${blacknr})
exten => s,n,Playback(if-correct-press&digits/1)
exten => s,n,Noop(Waiting for input)
exten => s,n(end),WaitExten(60,)
exten => s,n,Playback(sorry-youre-having-problems&goodbye)

exten => 1,1,GotoIf($[ "${blacknr}" != ""]?:personal-blacklist-add-invalid,s,1)
exten => 1,n,Set(DB(AMPUSER/${CALLERID(num)}/blacklist/${blacknr})=1)
exten => 1,n,Playback(num-was-successfully&added)
exten => 1,n,Wait(1)
exten => 1,n,Hangup

[personal-blacklist-add-invalid]
exten => s,1,Set(NumLoops=$[${NumLoops} + 1])
exten => s,n,Playback(pm-invalid-option)
exten => s,n,GotoIf($[${NumLoops} < 3]?personal-blacklist-add,s,start)
exten => s,n,Playback(goodbye)
exten => s,n,Hangup

[personal-blacklist-remove]
exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Playback(entr-num-rmv-blklist)
exten => s,n,Set(TIMEOUT(digit)=5)
exten => s,n,Set(TIMEOUT(response)=60)
exten => s,n,Read(blacknr,then-press-pound,,,,)
exten => s,n,SayDigits(${blacknr})
exten => s,n,Playback(if-correct-press&digits/1)
exten => s,n,Noop(Waiting for input)
exten => s,n(end),WaitExten(60,)
exten => s,n,Playback(sorry-youre-having-problems&goodbye)

exten => 1,1,Noop(Deleting: AMPUSER/${CALLERID(num)}/blacklist/${blacknr} ${DB_DELETE(AMPUSER/${CALLERID(num)}/blacklist/${blacknr})})
exten => 1,n,Playback(num-was-successfully&removed)
exten => 1,n,Wait(1)
exten => 1,n,Hangup

[app-blacklist-check-custom]
exten => _10XXX,1,Noop("app-blacklist-check-custom")
exten => _10XXX,n,Noop(${EXTEN})
exten => _10XXX,n,Noop(${CALLERID(num)})
exten => _10XXX,n,GotoIf($["${DB(AMPUSER/${EXTEN}/blacklist/${CALLERID(num)})}" = "1"]?app-blacklist-check,s,blacklisted)
exten => _10XXX,n,Return

[ext-findmefollow-custom]
exten => _FMPR-10XXX,1,Noop("CUSTOM-FOLLOWME")
exten => _FMPR-10XXX,n,Gosub(app-blacklist-check-custom,${EXTEN:5},1)
exten => _FMPR-10XXX,n,GotoIf($["${DB(AMPUSER/${EXTEN:5}/followme/announ_custom)}" != "1"]?NOANNOUN)
exten => _FMPR-10XXX,n,Answer
exten => _FMPR-10XXX,n,Wait(1)
exten => _FMPR-10XXX,n,Playback(custom/Hi_subscriber_you_are_calling_is_out_of_office)
exten => _FMPR-10XXX,n,Goto(ext-findmefollow,${EXTEN:5},DIALGRP)
exten => _FMPR-10XXX,n(NOANNOUN),Noop("NO ANNOUNCMENT")
exten => _FMPR-10XXX,n,Macro(dial-one,${RT},${DIAL_OPTIONS},${EXTEN:5})

Wednesday, February 22, 2017

An example of creating "out of office" function in the Asterisk (Elastix)

In this example, we create a function "out of office" in /etc/asterisk/extensions_custom.conf  for followme calls

Example:
Users phones: 10XXX

Then users can use this function from phones:
*11 - enable
*12 - disable


1. We have to record WAV files (PCM Encoded, 16 Bits, at 8000Hz) and add to Asterisk:
Sorry, subscriber out office
Hello, you set autoreply
Hello, you disable autoreply

2. Add to /etc/asterisk/extensions_custom.conf enable and disable blocks

[from-internal-custom]

;out of office enable
exten => *11,1,Answer
exten => *11,n,Wait(1)
exten => *11,n,Noop(${CALLERID(num)})
exten => *11,n,Set(DB(AMPUSER/${CALLERID(num)}/followme/announ_custom1)=1)
exten => *11,n,Playback(custom/Hi_you_enable_auto_reply_for_forwarding_call)
exten => *11,n,Hangup

;out of office disable
exten => *12,1,Answer
exten => *12,n,Wait(1)
exten => *12,n,Noop(${CALLERID(num)})
exten => *12,n,Set(DB(AMPUSER/${CALLERID(num)}/followme/announ_custom1)=0)
exten => *12,n,Playback(custom/Hi_you_disable_auto_reply_for_forwarding_call)
exten => *12,n,Hangup

3. Add to /etc/asterisk/extensions_custom.conf check blocks in Followme
[ext-findmefollow-custom]

;forward call, check out of office
exten => _FMPR-10XXX,1,Noop("CUSTOM-FOLLOWME")
exten => _FMPR-10XXX,n,GotoIf($["${DB(AMPUSER/${EXTEN:5}/followme/announ_custom1)}" != "1"]?NOANNOUN)
exten => _FMPR-10XXX,n,Answer
exten => _FMPR-10XXX,n,Wait(1)
exten => _FMPR-10XXX,n,Playback(custom/Hi_subscriber_you_are_calling_is_out_of_office)
exten => _FMPR-10XXX,n,Goto(ext-findmefollow,${EXTEN:5},DIALGRP)
exten => _FMPR-10XXX,n(NOANNOUN),Noop("NO ANNOUNCMENT")
exten => _FMPR-10XXX,n,Macro(dial-one,${RT},${DIAL_OPTIONS},${EXTEN:5})

Sunday, January 22, 2017

An example of creating the array with a list of phone numbers in the Asterisk

In this example, we create a variable and assign a list of numbers in /etc/asterisk/globals_custom.conf file.
Then we can use this variable in the dialplan /etc/asterisk/extensions_custom.conf.

1. Create a variable in /etc/asterisk/globals_custom.conf
TELS1 = "(18005532447|14085267209|18005536387)"
2. Example of use dialplan /etc/asterisk/extensions_custom.conf
exten = _1XXXXXXXXXX,1,GotoIf($["${CALLERID(num)}" : ${TELS1}]?eq)

...
exten = _1XXXXXXXXXX,n(eq),Noop("equal")