I had to create a test Yahoo email account today and apparently Captcha’s hate me as much as I hate them… Here’s my F you (Fuck You) captcha!
Author Archives: admin
Configuring AnyConnect SSL VPN Client Connections
Overview
ASA: 8.3+ (Written/Tested on 9.0)
Authentication: Local (Local ASA User Database)
Type: Split-tunnel OR Non split-tunnel
The below configurations will work with 8.3+, but was written and tested with 9.0. When setting up a Anyconnect VPN tunnel, you can push all traffic from the client over the VPN (Tunnel all) or you can use a split tunnel to only push traffic destined for selected subnets over the VPN tunnel. In laymen terms, the clients internet traffic originates from their ISP in a split tunnel, and it originates from the ASA when using tunnel all. The below configuration examples assume you have a basic setup equivalent to running factory-default and are setup to authenticate locally to the ASA. I will give examples of each configuration below.
Network Diagram
The ASA has a command that gives an overview of how to configure an Anyconnect SSL VPN, which in global configuration mode is vpnsetup ssl-remote-access steps. Here are the results of that command:
ciscoasa(config)# vpnsetup ssl-remote-access steps Steps to configure a remote access SSL VPN remote access connection and AnyConnect with examples: 1. Configure and enable interface interface GigabitEthernet0/0 ip address 10.10.4.200 255.255.255.0 nameif outside no shutdown interface GigabitEthernet0/1 ip address 192.168.0.20 255.255.255.0 nameif inside no shutdown 2. Enable WebVPN on the interface webvpn enable outside 3. Configure default route route outside 0.0.0.0 0.0.0.0 10.10.4.200 4. Configure AAA authentication and tunnel group tunnel-group DefaultWEBVPNGroup type remote-access tunnel-group DefaultWEBVPNGroup general-attributes authentication-server-group LOCAL 5. If using LOCAL database, add users to the Database username test password t3stP@ssw0rd username test attributes service-type remote-access Proceed to configure AnyConnect VPN client: 6. Point the ASA to an AnyConnect image webvpn svc image anyconnect-win-2.1.0148-k9.pkg 7. enable AnyConnect svc enable 8. Add an address pool to assign an ip address to the AnyConnect client ip local pool client-pool 192.168.1.1-192.168.1.254 mask 255.255.255.0 9. Configure group policy group-policy DfltGrpPolicy internal group-policy DfltGrpPolicy attributes vpn-tunnel-protocol svc webvpn
There are a few important things to note from Cisco’s directions:
- They are using the default names for configuring the group policy and tunnel groups, which will throw a warning that they already exist since they’re defaults
- The directions do not specify that you MUST attach the VPN Address pool to the tunnel group, which is necessary for it to work!
- They do not include how to create a split tunnel or a tunnel all to allow internet from the Anyconnect client.
- They are using outdated “svc” commands, which were replaced with “anyconnect”.
With that said, let’s move on to the configurations!
Anyconnect Configuration 1: Tunnel All
!Enable WebVPN, Set Anyconnect Image, and Enable Anyconnect config t webvpn enable outside tunnel-group-list enable anyconnect image disk0:/anyconnect-win-3.1.05178-k9.pkg 1 anyconnect image disk0:/anyconnect-macosx-i386-3.1.05178-k9.pkg 2 anyconnect image disk0:/anyconnect-linux-3.1.05178-k9.pkg 3 anyconnect enable end !Create DHCP Pool for Anyconnect Clients config t ip local pool pool-anyconnect 192.168.100.1-192.168.100.254 mask 255.255.255.0 end !Create Group Policy for Anyconnect config t group-policy GroupPolicy_Anyconnect internal group-policy GroupPolicy_Anyconnect attributes vpn-tunnel-protocol ssl-client end !Create Tunnel Group for Anyconnect config t tunnel-group TunnelGroup_Anyconnect type remote-access tunnel-group TunnelGroup_Anyconnect general-attributes authentication-server-group LOCAL default-group-policy GroupPolicy_Anyconnect address-pool pool-anyconnect tunnel-group TunnelGroup_Anyconnect webvpn-attributes group-alias 1-Admin enable end !Create NAT Exemption and Enable Outside Traffic to Enter/Exit the Same Interface config t object-group network obj-anyconnect network-object 192.168.100.0 255.255.255.0 exit nat (outside,outside) after-auto source dynamic obj-anyconnect interface same-security-traffic permit intra-interface end !Tunnel All Traffic Over Anyconnect VPN and Force Use of DNS Servers config t group-policy GroupPolicy_Anyconnect attributes split-tunnel-policy tunnelall split-tunnel-all-dns enable end !(OPTIONAL)Create Local User for Anyconnect config t username user1 password P@SSWORD username user1 attributes service-type remote-access end !(OPTIONAL) Add DNS Settings for Anyconnect Client config t group-policy GroupPolicy_Anyconnect attributes dns-server value 10.1.1.10 10.1.1.11 default-domain value domain.local end !(OPTIONAL) Allow Anyconnect IP Pool to Manage ASA config t ssh 192.168.100.0 255.255.255.0 inside http 192.168.100.0 255.255.255.0 inside management-access inside end !(OPTIONAL)Auto launch anyconnect config t group-policy GroupPolicy_Anyconnect attributes webvpn anyconnect ask none default anyconnect end
Anyconnect Configuration 2: Split Tunnel
!Enable WebVPN, Set Anyconnect Image, and Enable Anyconnect config t webvpn enable outside tunnel-group-list enable anyconnect image disk0:/anyconnect-win-3.1.05178-k9.pkg 1 anyconnect image disk0:/anyconnect-macosx-i386-3.1.05178-k9.pkg 2 anyconnect image disk0:/anyconnect-linux-3.1.05178-k9.pkg 3 anyconnect enable end !Create DHCP Pool for Anyconnect Clients config t ip local pool pool-anyconnect 192.168.100.1-192.168.100.254 mask 255.255.255.0 end !Create Group Policy for Anyconnect config t group-policy GroupPolicy_Anyconnect internal group-policy GroupPolicy_Anyconnect attributes vpn-tunnel-protocol ssl-client end !Create Tunnel Group for Anyconnect config t tunnel-group TunnelGroup_Anyconnect type remote-access tunnel-group TunnelGroup_Anyconnect general-attributes authentication-server-group LOCAL default-group-policy GroupPolicy_Anyconnect address-pool pool-anyconnect tunnel-group TunnelGroup_Anyconnect webvpn-attributes group-alias 1-Admin enable end !Create NAT Exemption config t object-group network obj-anyconnect network-object 192.168.100.0 255.255.255.0 exit nat (inside,outside) 2 source static any any destination static obj-anyconnect obj-anyconnect no-proxy-arp route-lookup end !Create Split Tunnel, Allow Access to VPN and Inside Subnets, and Apply to Group Policy config t access-list ACL_split-tunnel standard permit 192.168.100.0 255.255.255.0 access-list ACL_split-tunnel standard permit 10.1.1.0 255.255.255.0 group-policy GroupPolicy_Anyconnect attributes split-tunnel-policy tunnelspecified split-tunnel-network value ACL_split-tunnel end !(OPTIONAL)Create Local User for Anyconnect config t username user1 password P@SSWORD username user1 attributes service-type remote-access end !(OPTIONAL) Add DNS Settings for Anyconnect Client config t group-policy GroupPolicy_Anyconnect attributes dns-server value 10.1.1.10 10.1.1.11 default-domain value domain.local end !(OPTIONAL) Allow Anyconnect IP Pool to Manage ASA config t ssh 192.168.100.0 255.255.255.0 inside http 192.168.100.0 255.255.255.0 inside management-access inside end !(OPTIONAL)Auto launch anyconnect config t group-policy GroupPolicy_Anyconnect attributes webvpn anyconnect ask none default anyconnect end
Testing the Configuration
Open a web browser, connect to your ASA (https://vpn.domain.com OR https://172.31.100.1), and you’ll be prompted to login. You can login with the user account you’ve created in the configuration above. The Anyconnect client will automatically install, if it fails you may need to download and manually install it. Once installed, you can connect to your ASA by the outside interface (vpn.domain.com OR 172.31.100.1) and authenticate with the user you’ve created.
Additional Notes
You may wish to use a 3rd party SSL certificates (ie: Verisign, Thawte, Godaddy, etc) so end users do not get prompted about certificate warnings. Cisco ASA’s will regenerate it’s certificate upon reboot, and due to this you should create a self signed certificate whenever you cannot use a 3rd party. You can create the self signed certificate as follows:
!Create Self Signed Certificate config t crypto ca trustpoint SELF enroll enrollment self fqdn vpn.domain.com subject cn=vpn.domain.com,dc=domain,dc=com exit crypto ca enroll SELF !The following warnings will generate, answer accordingly as below: ! !WARNING: The certificate enrollment is configured with an fqdn !that differs from the system fqdn. If this certificate will be !used for VPN authentication this may cause connection problems. ! !Would you like to continue with this enrollment? [yes/no]: yes ! !The fully-qualified domain name in the certificate will be: vpn.domain.com ! !Include the device serial number in the subject name? [yes/no]: no ! !Generate Self-Signed Certificate? [yes/no]: yes ! !Attach the certificate to the outside interface ssl trust-point SELF outside end
DirMirror.vbs
Option Explicit '========================================================================= ' DirMirror.vbs ' VERSION: 1.0 ' AUTHOR: Brian Steinmeyer ' EMAIL: sigkill@sigkillit.com ' WEB: http://sigkillit.com ' DATE: 9/26/2013 ' REQUIREMENTS: ' - robocopy.exe (Built in to Server2008+, Windows 7+) ' - blat.exe, blat.dll. blat.lib in the same directory as the script (http://www.blat.net) ' - Blat profile installed to email results ' - Recommended to use Stunnel to Encrypt Email Sessions, Especially If the Email Server ' is not on your subnet ex: Gmail ' COMMENTS: Requires robocopy for the backup and blat to email results. Define ' the Directory Source(what you need to backup), the Directory Destination ' (where you need to backup to), path to blat, blat profile, email subject, ' and email body '========================================================================= ' ------ SCRIPT CONFIGURATION ------ Const WindowStyle = 0 '0=Hide Robocopy Console, 1=Show Robocopy Console Dim DirSource: DirSource = "\\server\share\directory" Dim DirDestination: DirDestination = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) & "backup" Dim intReturn 'Generic Return Dim logErrors: logErrors = Replace(WScript.ScriptFullName,".vbs","_log.txt") Dim emailBlatExe: emailBlatExe = "C:\blat\blat.exe" 'Custom Path to Blat.exe Default is Same Folder as Script Dim emailProfile: emailProfile = "gmail" 'Blat Profile Name See (http://www.blat.net) For Info Dim emailRecipient: emailRecipient = "email@domain.com" 'Email to Receive Backup Result Dim eSubject: eSubject = "Server1 Backup" Dim eBody: eBody = "Server1 Backup" ' ------ END CONFIGURATION ------ 'MAIN CALLS Call Logger(logErrors, "[" & Now() & "] " & vbCrLf & Wscript.ScriptName & vbCrLf & "Server: Spiceworks", True) Call AllowSingleInstance(".",logErrors, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody) Call ConfirmDirectories(logErrors, DirSource, DirDestination, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody) Call RoboDirMirror(logErrors, DirSource, DirDestination, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody) ' *************************************************************************************************** ' Function RoboDirMirror - Mirrors a Source Directory to a Mirror Directory Using Robocopy ' *************************************************************************************************** Private Sub RoboDirMirror(logName, strSource, strDestination, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody) 'On Error Resume Next Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Run Robocopy to Mirror Directory", False) 'Ensure Directories Don't End with Slash or Robocopy Will Error If Mid(strSource,Len(strSource),1) = "\" Then strSource = Mid(strSource,1,Len(strSource) - 1) End If If Mid(strDestination,Len(strDestination),1) = "\" Then strDestination = Mid(strDestination,1,Len(strDestination) - 1) End If Dim objShell: Set objShell = WScript.CreateObject("WScript.Shell") Dim strCommand: strCommand = "robocopy" Dim cmdOptions: cmdOptions = "/MIR /FFT /Z /XA:H /W:5 /log+:" & chr(34) & logName & chr(34) 'Robocopy \\SourceServer\Share \\DestinationServer\Share /MIR /FFT /Z /XA:H /W:5 Dim intReturn: intReturn = objShell.Run(strCommand & " " & chr(34) & strSource & chr(34) & " " & chr(34) & strDestination & chr(34) & " " & cmdOptions, WindowStyle, True) Select Case intReturn Case 0 'No Files Copied Call Logger(logName, "RESULT: Success - No Files Copied", False) emailSubject = emailSubject & " Success" emailBody = emailBody & " Success - No Files Copied" Case 1 'Files Copied Call Logger(logName, "RESULT: Success - Files Copied", False) emailSubject = emailSubject & " Success" emailBody = emailBody & " Success - Files Copied" Case 2 'File on Source Does Not Exist on Destination Call Logger(logName, "RESULT: Success - New Files Found in Source that are Not in Destination", False) emailSubject = emailSubject & " Success" emailBody = emailBody & " Success - New Files Found in Source that are Not in Destination" Case 3 'Combination of Case1 and Case2 Call Logger(logName, "RESULT: Success - Files Copied (New Files Found in Source that are Not in Destination)", False) emailSubject = emailSubject & " Success" emailBody = emailBody & " Success - Files Copied (New Files Found in Source that are Not in Destination)" Case Else 'Error Call Logger(logName, "RESULT: !~ERROR~! - Error Occurred on Robocopy", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " FAILED - Error Occurred on Robocopy" End Select If Err.Number <> 0 Then Err.Clear Call Logger(logName, "!~ERROR~! - Unknown Error Occurred in RoboDirMirror Sub", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " FAILED - Unknown Error Occurred in RoboDirMirror Sub" End If Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) End Sub ' *************************************************************************************************** ' Function ConfirmDirectories - Confirm Source and Destination Directories Exist ' *************************************************************************************************** Private Sub ConfirmDirectories(logName, strSource, strDestination, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody) 'On Error Resume Next Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Confirm Source/Destination Directories Exist", False) ' Create Objects Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Call Logger(logName, "SOURCE: " & strSource, False) Call Logger(logName, "DESTINATION: " & strDestination, False) If Not objFSO.FolderExists(strSource) Then 'Source Not Exist Call Logger(logName, "!~ERROR~! - Source Directory Does Not Exist, Quitting Script!", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " Failed - Source Directory Does Not Exist" Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) Wscript.Quit Else Call Logger(logName, "Success - Source Directory Exists", False) End If If Not objFSO.FolderExists(strDestination) Then 'Destination Not Exist Call Logger(logName, "Warning - Destination Directory Does Not Exist, Attempting to Create It", False) 'Attempt to Create Call CreateFileOrDir(strDestination) If Not objFSO.FolderExists(strDestination) Then Call Logger(logName, "!~ERROR~! - Failed to Create Destination Directory, Quitting Script!", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " Failed - Destination Directory Does Not Exist and Failed to Create It" Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) Wscript.Quit Else Call Logger(logName, "Success - Created Destination Directory", False) End If Else Call Logger(logName, "Success - Destination Directory Exists", False) End If If Err.Number <> 0 Then Err.Clear Call Logger(logName, "!~ERROR~! - Unknown Error in ConfirmDirectories Sub, Quitting Script", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " Failed - Unknown Error in ConfirmDirectories Sub" Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) Wscript.Quit End If End Sub ' *************************************************************************************************** ' Function AllowSingleInstance - Checks if only a single instance of the script is running - useful ' for repetitive scheduled tasks ' *************************************************************************************************** Private Sub AllowSingleInstance(strComputer, logName, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody) On Error Resume Next Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Confirm Single Instance of " & Wscript.ScriptName, False) Dim intReturn: intReturn = 0 '0=Success, 1=Error, 2=Warning Dim objWMIService: Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Dim colItems: Set colItems = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'cscript.exe'" & " OR Name = 'wscript.exe'") Dim intCount: intCount = 0 Dim objItem, strTemp For Each objItem in colItems If Not IsNull(objItem.CommandLine) Then strTemp = Right(objItem.CommandLine, Len(objItem.CommandLine) - InStrRev(objItem.CommandLine, chr(34) & " " & chr(34))) strTemp = Trim(Replace(strTemp, chr(34), "")) If StrComp(Wscript.ScriptFullName, strTemp, 1) = 0 Then intCount = intCount + 1 End If End If Next Call Logger(logName, "Detected Instances: " & intCount, False) If intCount > 1 Then 'Kill It Call Logger(logName, "!~ERROR~! - Only 1 instance is allowed, Quitting Script!", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " Backup FAILED - Detected " & intCount & " running instances" Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) Wscript.Quit End If If Err.Number <> 0 Then Err.Clear Call Logger(logName, "!~ERROR~! - Unknown Error in AllowSingleInstance Sub, Quitting Script!", False) emailSubject = emailSubject & " FAILED" emailBody = emailBody & " Backup FAILED - Unknown Error in AllowSingleInstance Sub" Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) Wscript.Quit End If On Error Goto 0 End Sub ' *************************************************************************************************** ' Function CreateFileOrDir ' *************************************************************************************************** Private Sub CreateFileOrDir(strPath) On Error Resume Next Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") If objFSO.DriveExists(objFSO.GetDriveName(strPath)) Then If StrComp(objFSO.GetExtensionName(strPath), "", 1) = 0 Then If Not objFSO.FolderExists(strPath) Then If objFSO.FolderExists(objFSO.GetParentFolderName(strPath)) Then objFSO.CreateFolder strPath 'Create Folder In Current Path Else CreateFileOrDir(objFSO.GetParentFolderName(strPath)) 'Recurse Creating Parent Folder CreateFileOrDir(strPath) 'Recurse Creating Current Folder End If End If Else If Not objFSO.FileExists(strPath) Then If objFSO.FolderExists(objFSO.GetParentFolderName(strPath)) Then objFSO.CreateTextFile strPath, True 'Create File In Current Path Else CreateFileOrDir(objFSO.GetParentFolderName(strPath)) 'Recurse Creating Parent Folder CreateFileOrDir(strPath) 'Recurse Creating Current Folder End If End If End If End If On Error Goto 0 End Sub ' *************************************************************************************************** ' Function SendBlatEmail - Sends Email Using Blat ' *************************************************************************************************** Private Sub SendBlatEmail(blatPath, blatProfile, strRecipients, strSubject, strBody, strAttachment) 'Need blat.exe, blat.dll, blat.lib On Error Resume Next Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Dim objShell: Set objShell = WScript.CreateObject("WScript.Shell") Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) 'Ensure Blat Exists If Not objFSO.FileExists(blatPath) Then If Not objFSO.FileExists(scriptPath & "blat.exe") Then Exit Sub Else blatPath = scriptPath & "blat.exe" End If End If 'Set Blat Email Command Dim commandText: commandText = chr(34) & blatPath & chr(34) commandText = commandText & " -p " & chr(34) & blatProfile & chr(34) commandText = commandText & " -to " & strRecipients commandText = commandText & " -subject " & chr(34) & strSubject & " " & chr(34) 'Keep Space to Prevent Escaping the Quote commandText = commandText & " -body " & chr(34) & strBody & " " & chr(34) 'Keep Space to Prevent Escaping the Quote 'Append Attachment(s) If objFSO.FileExists(strAttachment) Then commandText = commandText & " -attach " & chr(34) & strAttachment & chr(34) Else If objFSO.FileExists(scriptPath & strAttachment) Then commandText = commandText & " -attach " & chr(34) & scriptPath & strAttachment & chr(34) End If End If 'Send Blat Email objShell.run commandText, True Set objFSO = Nothing Set objShell = Nothing If Err.Number <> 0 Then Err.Clear End If On Error Goto 0 End Sub ' *************************************************************************************************** ' Function Logger ' *************************************************************************************************** Private Sub Logger(fileName, logMessage, blnNewLog) On Error Resume Next Const ForReading = 1, ForWriting = 2, ForAppending = 8 Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) Dim logName If InStr(1,fileName,"\",1) > 0 Then logName = fileName If objFSO.DriveExists(objFSO.GetDriveName(logName)) Then If StrComp(objFSO.GetExtensionName(logName), "", 1) = 0 Then If Not objFSO.FolderExists(logName) Then If objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then objFSO.CreateFolder logName 'Create Folder In Current Path Exit Sub Else Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog) 'Recurse Creating Parent Folder Call Logger(logName, logMessage, blnNewLog) 'Recurse Creating Current Folder Exit Sub End If End If Else If Not objFSO.FileExists(logName) Then If Not objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog) 'Recurse Creating Parent Folder Call Logger(logName, logMessage, blnNewLog) 'Recurse Creating Current Folder End If End If End If End If Else logName = scriptPath & fileName End If Dim logFile If blnNewLog = True Then Set logFile = objFSO.CreateTextFile(logName, True) Else If objFSO.FileExists(logName) Then Set logFile = objFSO.OpenTextFile(logName, ForAppending, True) Else Set logFile = objFSO.CreateTextFile(logName, True) End If End If logFile.WriteLine logMessage logFile.Close Set objFSO = Nothing On Error Goto 0 End Sub
How to Configure a Cisco ASA Site-to-Site IPSec VPN
This article will explain how to configure a Site-to-Site IPSec VPN using Cisco ASA 55XX’s using IKEV1. My example below shows how to configure VPN’s between 3 sites but can be modified for the following scenarios without much explanation:
- site-to-site VPN between 2 sites (Just remove SiteC… duh!)
- site-to-site to 3+ sites (just follow the example and modify for a N+1 sites. If You’re doing more than 3 sites, you may wish to look at a hub and spoke model to simply the network and backups, etc)
- Hub and spoke VPN, where 2 remote offices only connect to a main office (If SiteA is the Hub, on SiteB remove the SiteC configuration, on SiteC remove the SiteB configuration, etc…)
Overview
Network Diagram
Phase 1 Settings
Attribute | Value |
---|---|
Authentication | Preshared Keys |
Encryption | 3DES |
Hash | MD5 |
DH Group | Group 2 |
Lifetime | 86400 seconds |
Phase 2 Settings
Attribute | Value |
---|---|
Mode | Tunnel |
Encryption | 3DES |
Hash | SHA-1 |
PFS | Enabled |
Lifetime | 86400 seconds |
Configure SiteA
!----------------- !CONFIGURE OBJECTS !----------------- !Create Object for Local LAN SiteA config t object-group network obj-local network-object 10.0.1.0 255.255.255.0 end !Create Object for Remote LAN SiteB config t object-group network obj-SiteB network-object 10.0.2.0 255.255.255.0 end !Create Object for Remote LAN SiteC config t object-group network obj-SiteC network-object 10.0.3.0 255.255.255.0 end ! !--------------- !CONFIGURE ACL's !--------------- !Configure VPN ACL SiteB config t access-list ACL_SiteB extended permit ip object-group obj-local object-group obj-SiteB end !Configure VPN ACL SiteC config t access-list ACL_SiteC extended permit ip object-group obj-local object-group obj-SiteC end ! !------------------------ !CONFIGURE NAT EXEMPTIONS !------------------------ !Configure NAT Exemption SiteB config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteB obj-SiteB no-proxy-arp route-lookup end !Configure NAT Exemption SiteC config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteC obj-SiteC no-proxy-arp route-lookup end ! !----------------------------------------------------- !CONFIGURE PHASE1 PROPOSAL (pre-g2-3des-md5 SA:84600s) !----------------------------------------------------- config t crypto ikev1 policy 10 authentication pre-share encryption 3des hash md5 group 2 lifetime 86400 crypto ikev1 enable outside end ! !------------------------------------------------------------------- !CONFIGURE PHASE 2 PROPOSALS !------------------------------------------------------------------- !Configure Transform Set(g2-esp-3des-sha SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-SHA esp-3des esp-sha-hmac end !Configure Transform Set (g2-esp-3des-md5 SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-MD5 esp-3des esp-md5-hmac end !Configure Tunnel Group Remote WAN IP SiteB(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.2 type ipsec-l2l tunnel-group 1.1.1.2 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Tunnel Group Remote WAN IP SiteC(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.3 type ipsec-l2l tunnel-group 1.1.1.3 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Crypto Maps (You can only have 1 crypto map nam and each VPN needs an unique Map # to differentiate from each other) !MAP: SiteA=1, SiteB=2, SiteC=3 config t crypto map crypto-map 2 match address ACL_SiteB crypto map crypto-map 2 set peer 1.1.1.2 crypto map crypto-map 2 set transform-set ESP-3DES-SHA end config t crypto map crypto-map 3 match address ACL_SiteC crypto map crypto-map 3 set peer 1.1.1.3 crypto map crypto-map 3 set transform-set ESP-3DES-SHA end !Attach Crypto Map to Interface config t crypto map crypto-map interface outside end
Configure SiteB
!----------------- !CONFIGURE OBJECTS !----------------- !Create Object for Local LAN SiteB config t object-group network obj-local network-object 10.0.2.0 255.255.255.0 end !Create Object for Remote LAN SiteA config t object-group network obj-SiteA network-object 10.0.1.0 255.255.255.0 end !Create Object for Remote LAN SiteC config t object-group network obj-SiteC network-object 10.0.3.0 255.255.255.0 end ! !--------------- !CONFIGURE ACL's !--------------- !Configure VPN ACL SiteA config t access-list ACL_SiteA extended permit ip object-group obj-local object-group obj-SiteA end !Configure VPN ACL SiteC config t access-list ACL_SiteC extended permit ip object-group obj-local object-group obj-SiteC end ! !------------------------ !CONFIGURE NAT EXEMPTIONS !------------------------ !Configure NAT Exemption SiteA config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteA obj-SiteA no-proxy-arp route-lookup end !Configure NAT Exemption SiteC config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteC obj-SiteC no-proxy-arp route-lookup end ! !----------------------------------------------------- !CONFIGURE PHASE1 PROPOSAL (pre-g2-3des-md5 SA:84600s) !----------------------------------------------------- config t crypto ikev1 policy 10 authentication pre-share encryption 3des hash md5 group 2 lifetime 86400 crypto ikev1 enable outside end ! !------------------------------------------------------------------- !CONFIGURE PHASE 2 PROPOSALS !------------------------------------------------------------------- !Configure Transform Set(g2-esp-3des-sha SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-SHA esp-3des esp-sha-hmac end !Configure Transform Set (g2-esp-3des-md5 SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-MD5 esp-3des esp-md5-hmac end !Configure Tunnel Group Remote WAN IP SiteA(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.1 type ipsec-l2l tunnel-group 1.1.1.1 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Tunnel Group Remote WAN IP SiteC(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.3 type ipsec-l2l tunnel-group 1.1.1.3 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Crypto Maps (You can only have 1 crypto map nam and each VPN needs an unique Map # to differentiate from each other) !MAP: SiteA=1, SiteB=2, SiteC=3 config t crypto map crypto-map 1 match address ACL_SiteA crypto map crypto-map 1 set peer 1.1.1.1 crypto map crypto-map 1 set transform-set ESP-3DES-SHA end config t crypto map crypto-map 3 match address ACL_SiteC crypto map crypto-map 3 set peer 1.1.1.3 crypto map crypto-map 3 set transform-set ESP-3DES-SHA end !Attach Crypto Map to Interface config t crypto map crypto-map interface outside end
Configure SiteC
!----------------- !CONFIGURE OBJECTS !----------------- !Create Object for Local LAN SiteC config t object-group network obj-local network-object 10.0.3.0 255.255.255.0 end !Create Object for Remote LAN SiteA config t object-group network obj-SiteA network-object 10.0.1.0 255.255.255.0 end !Create Object for Remote LAN SiteB config t object-group network obj-SiteB network-object 10.0.2.0 255.255.255.0 end ! !--------------- !CONFIGURE ACL's !--------------- !Configure VPN ACL SiteA config t access-list ACL_SiteA extended permit ip object-group obj-local object-group obj-SiteA end !Configure VPN ACL SiteB config t access-list ACL_SiteB extended permit ip object-group obj-local object-group obj-SiteB end ! !------------------------ !CONFIGURE NAT EXEMPTIONS !------------------------ !Configure NAT Exemption SiteA config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteA obj-SiteA no-proxy-arp route-lookup end !Configure NAT Exemption SiteB config t nat (inside,outside) 1 source static obj-local obj-local destination static obj-SiteB obj-SiteB no-proxy-arp route-lookup end ! !----------------------------------------------------- !CONFIGURE PHASE1 PROPOSAL (pre-g2-3des-md5 SA:84600s) !----------------------------------------------------- config t crypto ikev1 policy 10 authentication pre-share encryption 3des hash md5 group 2 lifetime 86400 crypto ikev1 enable outside end ! !------------------------------------------------------------------- !CONFIGURE PHASE 2 PROPOSALS !------------------------------------------------------------------- !Configure Transform Set(g2-esp-3des-sha SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-SHA esp-3des esp-sha-hmac end !Configure Transform Set (g2-esp-3des-md5 SA:84600s PFS:enabled) config t crypto ipsec ikev1 transform-set ESP-3DES-MD5 esp-3des esp-md5-hmac end !Configure Tunnel Group Remote WAN IP SiteA(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.1 type ipsec-l2l tunnel-group 1.1.1.1 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Tunnel Group Remote WAN IP SiteB(Replace VPNSHAREDKEYPW) config t tunnel-group 1.1.1.2 type ipsec-l2l tunnel-group 1.1.1.2 ipsec-attributes pre-shared-key VPNSHAREDKEYPW end !Configure Crypto Maps (You can only have 1 crypto map nam and each VPN needs an unique Map # to differentiate from each other) !MAP: SiteA=1, SiteB=2, SiteC=3 config t crypto map crypto-map 1 match address ACL_SiteA crypto map crypto-map 1 set peer 1.1.1.1 crypto map crypto-map 1 set transform-set ESP-3DES-SHA end config t crypto map crypto-map 2 match address ACL_SiteB crypto map crypto-map 2 set peer 1.1.1.2 crypto map crypto-map 2 set transform-set ESP-3DES-SHA end !Attach Crypto Map to Interface config t crypto map crypto-map interface outside end
Further Info
I would suggest using IKEV2 for a Site-to-Site VPN, and I’ll outline the steps a in future article once I get time to write it up…. Stay tuned!
Convert a WLC LDPE Image to Non-LDPE
If you ever purchase a used Cisco Wireless LAN Controller or receive one on RMA, you may run into an issue when you attempt to upgrade the image and receive the following error:
ERROR: Incompatible SW image.ERROR: Please install the Data Payload Encryption licensed image
This issue occurs because the Controller has an LDPE image installed, which is only needed in Russia where Data DTLS Payload Encryption is regulated by the Government. Cisco only recommends using this image if you reside in Russia. To resolve this issue and put the standard image on, follow these steps:
Step 1 – Confirm you have an LDPE image installed
From the console, enter the show sysinfo command and confirm the build type is DATA + WPS + LDPE
Step 2 – Upgrade to LDPE Image version 7.0.230.0
LDPE Image version 7.0.230.0 (ex: AIR-CT5500-LDPE-K9-7-0-230-0.aes for a 5508) introduced the ability to move to a normal image once a DTLS license is installed (Resolved Caveat CSCtw78061). If the product version is not already on that image, download it, and install it.
Step 3a – Confirm a DTLS License is Installed
From the console, enter the show license summary and ensure under the Feature: data encryption section it shows License State: Active, In Use. If you see this, then continue to step 4, otherwise you must download a free DTLS license and install it.
Step 3b – Download a DTLS License
- Go to https://tools.cisco.com/SWIFT/LicensingUI/Quickstart
- Click Get New->IPS, Crypto, Other Licenses
- Click Wireless, then click Cisco Wireless Controllers (2500/5500/7500/WISM2) DTLS License
- Choose the Controller Platform, enter the Product ID, enter the Serial Number, and click Next
- You can retrieve the PID and SN by running show license UDI at the console
- Select I agree with the Terms of the License, confirm your email address, and click Get License
Step 3c – Install the DTLS License
- Copy the DTLS license to the root of your TFTP server
- At the console, run the following command to install your license
- license install tftp://<TFTP_IP>/XXXX.lic
- Replace <TFTP_IP> with the IP address of your TFTP servver
- Replace XXXX.lic with the name of your license
- Save your configuration and reboot the WLC
- save config
- reset system
Step 4 – Install the Non-LDPE Image
You can now install any Non-LDPE Image as needed!
DeleteOldUsers.vbs
'========================================================================= ' DeleteOldUsers.vbs ' VERSION: 1.0 ' AUTHOR: Brian Steinmeyer ' EMAIL: sigkill@sigkillit.com ' WEB: http://sigkillit.com ' DATE: 4/22/2014 ' USER TERMINATION POLICY: ' - Reset PW ' - Set description to termination date ' - Optionally forward email ' - Move terminated users to specified OU ' COMMENTS: This script works in conjunction with the above user termination ' policy. Specify the OU containing old users and set the number of retention ' days to keep an AD user account after the termination date. You can schedule ' the script to run daily to delete any old users. to permanently delete ' those users after X amount of days. '========================================================================= Option Explicit ' ------ SCRIPT CONFIGURATION ------ Dim oldUserOU: oldUserOU = "OU=Old Users,OU=User,DC=domain,DC=local" Dim oldUserRetentionDays: oldUserRetentionDays = 30 Dim logResults: logResults = Replace(WScript.ScriptFullName,".vbs","_logs\") & Replace(WScript.ScriptName,".vbs","_") & FixDate(Date()) & Replace(FormatDateTime(Time,4), ":", "") & ".txt" Dim logRetentionDays: logRetentionDays = 30 Dim emailBlatExe: emailBlatExe = "c:\blat\blat.exe" 'Custom Path to Blat.exe Default is Same Folder as Script Dim emailProfile: emailProfile = "alert" 'Blat Profile Name See (http://www.blat.net) For Info Dim emailRecipient: emailRecipient = "alert.admin@domain.com" 'Email to Receive Backup Result Dim blnEmailOnlyOnDelete: blnEmailOnlyOnDelete = true 'True = Only email results when at least 1 user is deleted ' ------ END CONFIGURATION ------ 'MAIN CALLS Call TerminateOldUsers(oldUserRetentionDays,oldUserOU,logResults) Call SendResults(logResults,blnEmailOnlyOnDelete,emailBlatExe,emailProfile,emailRecipient) Call PurgeLogs(Replace(WScript.ScriptFullName,".vbs","_logs\"),logRetentionDays,".txt") ' *************************************************************************************************** ' Sub TerminateOldUsers - Parse Old Users and Delete after X days ' *************************************************************************************************** Private Sub TerminateOldUsers(intDays,strOU,logName) On Error Resume Next 'Start Error Handling 'Create Log File Call Logger(logName, "DATE:" & Now() & vbCrLf & "USER_OU:" & strOU & vbCrLf & "RETENTION_DAYS:" & intDays, True) 'Search OU For Users Dim objConnection: Set objConnection = CreateObject("ADODB.Connection") Dim objCommand: Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCommand.ActiveConnection = objConnection objCommand.Properties("Page Size") = 1000 'Override the Return 1000 Results Default Const ADS_SCOPE_SUBTREE = 2 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'Include Sub OU's objCommand.CommandText = "SELECT ADsPath, cn FROM 'LDAP://" & strOU & "' WHERE objectCategory='person' AND objectClass='user'" Dim objRecordSet: Set objRecordSet = objCommand.Execute 'Parse Users If objRecordSet.RecordCount > 0 Then objRecordSet.MoveFirst Dim objUser, objParent, strDescription Dim strResult: strResult = "" Do Until objRecordSet.EOF Set objUser = GetObject(objRecordSet.Fields("ADsPath").Value) strDescription = objUser.description If strDescription = "" Then strDescription = "BLANK" End If 'Only Evaluate Users with Date for Description If IsDate(objUser.Description) Then If DateDiff("d",objUser.Description,Date) > intDays Then 'Delete User Past Retention Date strResult = "DELETE" Set objParent = GetObject(objUser.Parent) objParent.Delete "user", "CN=" & objRecordSet.Fields("cn").Value Else strResult = "IGNORE" End If Else strResult = "IGNORE" End If 'Log Results If Err.Number <> 0 Then Err.Clear strResult = "!~ERROR!~" End If Call Logger(logName, strResult & ":(" & strDescription & "):" & objRecordSet.Fields("ADsPath").Value, False) objRecordSet.MoveNext Loop Else Call Logger(logName, "NOUSERS:" & strOU, False) End If On Error Goto 0 'End Error Handling End Sub ' ***************************************************************** ' Sub SendResults - Parse Log File and Send Results ' ***************************************************************** Private Sub SendResults(logName, blnEmail, emailBlatExe, emailProfile, emailRecipient) On Error Resume Next ' Create Objects Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") 'Parse Log File Dim intDelete: intDelete = 0 Dim intTotal: intTotal = 0 Dim intError: intError = 0 Dim strLine Dim logFile: Set logFile = objFSO.OpenTextFile(logName, 1) Do Until logFile.AtEndOfStream strLine = logFile.ReadLine If InStr(1, strLine, "IGNORE:", 1) Then intTotal = intTotal + 1 End If If InStr(1, strLine, "DELETE:", 1) Then intTotal = intTotal + 1 intDelete = intDelete + 1 End If If InStr(1, strLine, "!~ERROR~!:", 1) Then intTotal = intTotal + 1 intError = intError + 1 End If If InStr(1, strLine, "NOUSERS:", 1) Then 'No Users End If Loop logFile.Close 'Set Email Subject Dim emailSubject: emailSubject = Replace(WScript.ScriptName,".vbs","") If intError > 0 Then emailSubject = emailSubject & " - Error" Else emailSubject = emailSubject & " - Deleted " & intDelete & " Users" End If 'Set Email Body Dim emailBody: emailBody = "TOTAL USERS: " & intTotal & vbCrLf & _ "ERRORS: " & intError & vbCrLf & _ "DELETED: " & intDelete 'Email Results If blnEmail = true Then If intDelete > 0 Then Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) End If Else Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName) End If 'Cleanup Objects Set objFSO = Nothing On Error Goto 0 End Sub ' *************************************************************************************************** ' Function SendBlatEmail - Sends Email Using Blat ' *************************************************************************************************** Private Sub SendBlatEmail(blatPath, blatProfile, strRecipients, strSubject, strBody, strAttachment) 'Need blat.exe, blat.dll, blat.lib On Error Resume Next Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Dim objShell: Set objShell = WScript.CreateObject("WScript.Shell") Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) 'Ensure Blat Exists If Not objFSO.FileExists(blatPath) Then If Not objFSO.FileExists(scriptPath & "blat.exe") Then Exit Sub Else blatPath = scriptPath & "blat.exe" End If End If 'Set Blat Email Command Dim commandText: commandText = chr(34) & blatPath & chr(34) commandText = commandText & " -p " & chr(34) & blatProfile & chr(34) commandText = commandText & " -to " & strRecipients commandText = commandText & " -subject " & chr(34) & strSubject & " " & chr(34) 'Keep Space to Prevent Escaping the Quote commandText = commandText & " -body " & chr(34) & strBody & " " & chr(34) 'Keep Space to Prevent Escaping the Quote 'Append Attachment(s) If objFSO.FileExists(strAttachment) Then commandText = commandText & " -attach " & chr(34) & strAttachment & chr(34) Else If objFSO.FileExists(scriptPath & strAttachment) Then commandText = commandText & " -attach " & chr(34) & scriptPath & strAttachment & chr(34) End If End If 'Send Blat Email objShell.run commandText, True Set objFSO = Nothing Set objShell = Nothing If Err.Number <> 0 Then Err.Clear End If On Error Goto 0 End Sub ' *************************************************************************************************** ' Sub PurgeLogs - Deletes Old Log FIles ' *************************************************************************************************** Private Sub PurgeLogs(logFolder,intDays,strExtension) On Error Resume Next Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Dim objFolder: Set objFolder = objFSO.GetFolder(logFolder) Dim file For Each file In objFolder.Files If StrComp(Right(file.Name, Len(strExtension)),strExtension) = 0 Then If DateDiff("d", file.DateLastModified, Now) > intDays Then objFSO.DeleteFile(file), True End If End If Next Set objFSO = Nothing If Err.Number <> 0 Then Err.Clear End If On Error Goto 0 End Sub ' *************************************************************************************************** ' Function FixDate - Ensures Single Digit Numbers Have 0 In Front ' *************************************************************************************************** Function FixDate(strDate) Dim arrTemp Dim M, D, Y arrTemp = Split(strDate, "/") M = arrTemp(0) D = arrTemp(1) Y = arrTemp(2) If (M>=0) And (M<10) Then M = "0" & M If (D>=0) And (D<10) Then D = "0" & D 'If (Y>=0) And (Y<10) Then Y = "0" & Y FixDate = M & D & Y End Function ' *************************************************************************************************** ' Function Logger ' *************************************************************************************************** Private Sub Logger(fileName, logMessage, blnNewLog) On Error Resume Next Const ForReading = 1, ForWriting = 2, ForAppending = 8 Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject") Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) Dim logName If InStr(1,fileName,"\",1) > 0 Then logName = fileName If objFSO.DriveExists(objFSO.GetDriveName(logName)) Then If StrComp(objFSO.GetExtensionName(logName), "", 1) = 0 Then If Not objFSO.FolderExists(logName) Then If objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then objFSO.CreateFolder logName 'Create Folder In Current Path Exit Sub Else Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog) 'Recurse Creating Parent Folder Call Logger(logName, logMessage, blnNewLog) 'Recurse Creating Current Folder Exit Sub End If End If Else If Not objFSO.FileExists(logName) Then If Not objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog) 'Recurse Creating Parent Folder Call Logger(logName, logMessage, blnNewLog) 'Recurse Creating Current Folder End If End If End If End If Else logName = scriptPath & fileName End If Dim logFile If blnNewLog = True Then Set logFile = objFSO.CreateTextFile(logName, True) Else If objFSO.FileExists(logName) Then Set logFile = objFSO.OpenTextFile(logName, ForAppending, True) Else Set logFile = objFSO.CreateTextFile(logName, True) End If End If logFile.WriteLine logMessage logFile.Close Set objFSO = Nothing On Error Goto 0 End Sub
Matching Credit Card Numbers
Overview
Using regular expressions, you can easily match a credit card number. You may wish to validate legit CC numbers, block financial information in emails, or audit security by finding financial information in documents. There is no perfect algorithm or regex for detecting potential CCN’s, and there will always be false positives, etc. Although regular expressions can match a CCN, they cannot confirm incorrect digits. If you require a more robust solution, you will need to also implement the Luhn algorithm. Moving forward, I’ll focus on detecting CCN’s in documents or emails.
Credit Card Info
The first 6 digits of a CCN are known as the Issuer Identification Number (IIN), which are used to identify the card issuer; the remaining digits can vary in length and are up to the issuer. Using the IIN and the CCN pre-defined length, we can identify blocks of numbers that belong to each issuer. The credit card numbers are typically grouped with spaces or dashes in order to make them more readable. We will need to keep this in mind when matching CCN’s. I have listed US issuers, their IIN, and the CCN lengths below. For a full list including international issuers see http://en.wikipedia.org/wiki/Bank_card_number.
ISSUER | IIN STARTING PATTERN | LENGTH |
---|---|---|
American Express | 34, 37 | 15 |
Diners Club | 300-305, 309, 36, 38-39 | 15 |
Discover | 6011, 622126-622925, 644-649, 65 | 16 |
JCB | 3528-3589 | 16 |
MasterCard | 50-55 | 16 |
Visa | 4 | 16 or 13 on old cards |
The Basics Validating Credit Cards
If we wanted to validate a credit card, you would first want to remove any spaces or dashes from the input. Once the input is clean we can use a typical regular expression to match potential valid CCN’s. The below regex’s were originally taken from http://www.regular-expressions.info/creditcard.html, but I’ve updated the out of date expressions in accordance to the latest IIN changes as per the Wikipedia article listed above:
American Express
^3[47][0-9]{13}$
Diners Club
^3(?:0[0-5]|09|[68][0-9])[0-9]{11}$
Discover
^6(?:011|22[0-9]|5[0-9]{2})[0-9]{12}$
JCB
^35(?:2[89]|[3-8][0-9])[0-9]{12}$
Mastercard
^5[0-5][0-9]{14}$
Visa
^4[0-9]{12}(?:[0-9]{3})?$
However, if you are unable to strip the spaces and dashes out prior to validating the CCN, you’ll quickly find many shortcomings. The above regex’s will not account for spaces or dashes as printed on the front of the card and will only detect a CCN when it’s the only thing on a line. Obviously, this will not give us the results we desire for finding CCN’s in a document or email. Instead, we will want to use \b to match on a word boundary instead of the carrot(^) and the dollar($). In addition, we also want to add exceptions before and after the CCN we’re checking, which will help reduce false positives; this will allow us to eliminate items such as hyperlinks, order #’s, etc. We can now use the below regex to surround each CC issuer’s rules that we want to detect:
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)CCN(?!\/)\b
- Starting Position is a word boundary
- Previous Character is not:
- period(.)
- left angle bracket(<)
- right angle bracket(>)
- dash(–)
- plus(+)
- forward slash(/) – Ignore false positives like http://www.domain.com/################/
- Open parenthesis – Ignore false positives like (################)
- Equal (=) – Ignores false positives like http://www.domain.com?si=################
- Pound, Colon, Space(#: ) – Ignore false positives like Order#: ################
- dash, space(– )
- ID, colon, space(ID: )
- CCN – Represents the regex used to represent each issuers credit card number
- Next character is not:
- forward slash(/) – Ignore false positives like http://www.domain.com/################/
- Ending position is a word boundary
Matching Credit Cards in a Document or Email
By doing a slight re-write of CC regex’s and combining it with our above wrapper, we can easily detect a CCN’s in a document or email. However, the oneliner for Discover CCN’s is quite long, and some systems limit the length of regex’s. Due to this, I’ve provided the oneliner plus shorter versions split up by the IIN.
American Express
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)3[47](?:\d{13}|\d{2}\s\d{6}\s\d{5}|\d{2}\-\d{6}\-\d{5})(?!\/)\b
Diners Club
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)3(?:0[0-5]|09|[689]\d)\d(?:\d{10}|\s\d{6}\s\d{4}|\-\d{6}\-\d{4})(?!\/)\b
Discover (Oneliner)
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)(?:6011\d{12}|6011(\s\d{4}){3}|6011(\-\d{4}){3}|64[4-9]\d{13}|64[4-9]\d(\s\d{4}){3}|64[4-9]\d(\-\d{4}){3}|65\d{14}|65\d{2}(\s\d{4}){3}|65\d{2}(\-\d{4}){3}|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5])\d{10}|622(1\s2[6-9]|1\s[3-9][0-9]|[2-8]\s[0-9]{2}|9\s[0-1][0-9]|9\s2[0-5])\d{2}(\s\d{4}){2}|622(1\-2[6-9]|1\-[3-9][0-9]|[2-8]\-[0-9]{2}|9\-[0-1][0-9]|9\-2[0-5])\d{2}(\-\d{4}){2})(?!\/)\b
Discover (6011,644-649,65 IIN’s)
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)6(?:011|4[4-9]\d|5\d{2})(?:\d{12}|(\s\d{4}){3}|(\-\d{4}){3})(?!\/)\b
Discover (622 IIN No Delimiter)
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5])\d{10}(?!\/)\b
Discover (622 IIN Space Delimiter)
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s)622(1\s2[6-9]|1\s[3-9][0-9]|[2-8]\s[0-9]{2}|9\s[0-1][0-9]|9\s2[0-5])\d{2}(\s\d{4}){2}(?!\/)\b
Note: Office 365 has a 128 character limit for the regex expression. I have modified the default wrapper by removing a few items to keep this at 128 characters
Discover (622 IIN Dash Delimiter)
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s)622(1\-2[6-9]|1\-[3-9][0-9]|[2-8]\-[0-9]{2}|9\-[0-1][0-9]|9\-2[0-5])\d{2}(\-\d{4}){2}(?!\/)\b
Note: Office 365 has a 128 character limit for the regex expression. I have modified the default wrapper by removing a few items to keep this at 128 characters
JCB
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)35(?:2[89]|[3-8]\d)(?:\d{12}|(\s\d{4}){3}|(\-\d{4}){3})(?!\/)\b
MasterCard
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)5[0-5](?:\d{14}|\d{2}(\s\d{4}){3}|\d{2}(\-\d{4}){3})(?!\/)\b
Visa
\b(?<![\.\<\>\-\+\/\(\=]|#:\s|\-\s|ID:\s)4(?:\d{11}|\d{3}\s(\d{4}\s){2}|\d{3}\-(\d{4}\-){2})\d(\d{3})?(?!\/)\b
If we test the above regex in an online tester, we can verify it’s working as expected. As you can see, our regex is capturing our test Visa CCN’s and missing a lot of false positives:
Real World Ex: Blocking Emails with Credit Card Numbers in Office 365
Now that we’ve established our regex’s, let’s apply it to a real world example. For our example, we’ll block inbound/outbound email in Office 365. Please note, Office 365 transport rules only allow 128 characters in a regex, and due to this we’ll need to use multiple regex’s for matching Discover. Also note, two of the Discover Regex’s I used above have a modified wrapper to keep them at the 128 character limit.
- Login to the Office 365 Admin Portal (https://portal.microsoftonline.com)
- Click Admin then click Exchange
- Under the Exchange Admin Center, click Mail Flow
- Click the Rules tab
- Click the + to create a new rule
- Name: Block Emails with Credit Card Numbers
- Apply this rule if: The subject or body matches:
- Paste each CCN Regex
- Do the following: Reject the message with the explanation
- Rejection Reason: Your message was blocked due to the detection of a Credit Card Number
- Click Save
- Note: Mail flow rules normally take 30-35 minutes to replicate in Office 365
Block Outbound Email for Specific Users
Overview
There are a few situations where you may need to restrict certain users from sending email to external users. For example, you may have part time employees that only need to send email to internal users OR you might have an employee who’s about to get terminated and don’t want them emailing clients. Fortunately, in Office 365 Exchange you can create a Mail Flow Rule to accomplish this.
Create Distribution Group to Define Users to Block Outbound Email
In order for the mail flow rule to see the group, it must be a distribution group. However, you can easily hide it from the GAL so your users don’t see it. Many organizations use CustomAttribute15 to define what displays in there GAL. If that’s your case, simply do not define CustomAttribute15 or define it to a value so it does not show in your GAL; otherwise, set the attribute to Hide group from Exchange Address Lists.
- Create a new distribution group
- Name: Block Outbound Email
- Email: blockoutboundemail@<company>.onmicrosoft.com
- Members: Add any user you want to block from sending outbound emails to external recipients (They will only be able to send to internal recipients)
- If you are using Office 365 in a Hybrid Deployment, make sure you use dirsync to synchronizes your new group
Create Mail Flow Rule
In this example, we will prevent a user from sending emails to any external recipients, but they will still be able to send to internal recipients.
- Login to the Office 365 Admin Portal https://portal.microsoftonline.com
- Click Admin then click Exchange to open the Exchange Admin Center
- Click mail flow then click on the Rules tab
- Click the + symbol and click Create a new rule
- Name the rule Block Outbound Emails to External Recipients
- Under Apply this rule if, click the recipient is located
- Select Outside the organization and click OK
- Click More Options to add another condition
- Click Add Condition
- On the new condition, select the sender is a member of this group
- Search and select the group Block Outbound Emails and click OK
- Note: Despite the wording stating “member of this group”, you can select a user instead of a group. However, it’s easier to manage and you do not need to wait for the mail flow rule to propagate on 365, which can take up to an hour in my testing.
- Under Do the following, select Block the message then click delete the message without notifying anyone, and click OK
- Click Save
IMPORTANT NOTE: It can take up to 45 minutes for Microsoft’s back end to fully synchronize rules! This means any new or modified rules can take up to 45 minutes to take effect!
Delivery Report in Outlook or Outlook Web App
Overview
When using Outlook or Outlook Web App (OWA) in an Office 365 or Exchange environment, you can track the message from the client side. Both Outlook and OWA allow you to view a delivery report in order to confirm a message was delivered when the recipient claims they have not received it or if it’s taking a long time to deliver. Delivery reports work for both internal and external recipients.
View a Delivery Report in Outlook
- In Outlook, go to your Sent Items folder
- Locate the message you want to track and open it
- Click File, click Info, and click Open Delivery Report
View a Delivery Report in Outlook Web App (OWA)
If you are using any other email client than Outlook (mobile device, OWA, etc), you can use OWA to view a delivery report.
- Login to OWA at https://portal.microsoftonline.com
- Click the Gear Icon, then click Options
- Click Organize Email then click Delivery Reports
- Enter your search criteria, click Search
- Select the email you want to track and click the Pencil Icon to view the delivery report
Review Delivery Report
Internal delivery reports will show Delivered upon success delivering. Also note, Office 365 Exchange only keeps message tracking data for 14 days.
External delivery reports will only show Transferred which means it successfully sent out from your mail server. However, this does not guarantee the recipient received the email because there can be issues on the recipients email server.
365Licenses.ps1
#========================================================================= # 365Licenses.ps1 # VERSION: 1.0 # AUTHOR: Brian Steinmeyer # EMAIL: sigkill@sigkillit.com # WEB: http://sigkillit.com # DATE: 4/4/20114 # REQUIREMENTS: # 1) Microsoft Online Services Sign-In Assistant for IT Professionals # -(http://www.microsoft.com/en-gb/download/details.aspx?id=28177) # 2) Windows Azure Active Directory Module for Windows PowerShell # -(http://technet.microsoft.com/en-us/library/jj151815.aspx#bkmk_installmodule) # COMMENTS: This script is intended to retrieve Office 365 licensing information # by accepted domains. It will provide the active license count by domain, # estimate the cost per domain, and provide the number of unused licenses. #========================================================================= # ------ SCRIPT CONFIGURATION ------ # Define License Unit Cost $intCost = 3.88 # ------ END CONFIGURATION ------ # Connect to Microsoft Online write-host "Connecting to Office 365..." Import-Module MSOnline Try { Connect-MsolService -ErrorAction Stop } Catch { Write-Host $error[0].Exception -ForegroundColor Red -BackgroundColor Black Write-Host "Error Connecting to Office 365... Quitting Script!" -ForegroundColor Red -BackgroundColor Black Break } # Get Office 365 Accepted Domains and Active User Licenses Try { $arrDomains = @(Get-MsolDomain) } Catch { Write-Host "Error Retrieving Office 365 Accepted Domains... Quitting Script!" -ForegroundColor Red -BackgroundColor Black Break } $arrCompany = @() $TotalLicenses = 0 $TotalCost = 0 foreach ($d in $arrDomains){ $domain = $d.Name write-host ("PROCESSING: " + $domain.ToUpper()) $users = Get-MsolUser -All | where {$_.isLicensed -eq "True" -and $_.UserPrincipalName.Contains($domain)} | Select DisplayName, UserPrincipalName -ExpandProperty Licenses | Select DisplayName, UserPrincipalName, AccountSkuID If ($users.count -ne $null){ $i = $users.count $users | format-table $users | Export-Csv ("365_Licenses_" + $domain.replace(".","_") + ".csv") } Else{ $i = 0 Write-Host "0 Licenses<code>n</code>n" } $objCompany = New-Object -TypeName PSObject $objCompany | Add-Member -Name 'Domain' -MemberType Noteproperty -Value $domain $objCompany | Add-Member -Name 'Licenses' -MemberType Noteproperty -Value $i $objCompany | Add-Member -Name 'Cost' -MemberType Noteproperty -Value ("{0:C2}" -f ($i * $intCost)) $arrCompany += $objCompany $TotalLicenses += $i $TotalCost += ($i * $intCost) } # Get Company Licensing Info Try { $companyLicenses = Get-MsolAccountSku | Select AccountSkuId, ActiveUnits, WarningUnits, ConsumedUnits } Catch { Write-Host $error[0].Exception -ForegroundColor Red -BackgroundColor Black Write-Host "Error Retrieving Office 365 Account Info... Quitting Script!" -ForegroundColor Red -BackgroundColor Black Break } $objCompany = New-Object -TypeName PSObject $objCompany | Add-Member -Name 'Domain' -MemberType Noteproperty -Value "TOTAL ACTIVE LICENSES" $objCompany | Add-Member -Name 'Licenses' -MemberType Noteproperty -Value $TotalLicenses $objCompany | Add-Member -Name 'Cost' -MemberType Noteproperty -Value ("{0:C2}" -f $TotalCost) $arrCompany += $objCompany $unusedLicenses = ($companyLicenses.ActiveUnits - $companyLicenses.ConsumedUnits) $unusedCost = ($unusedLicenses * $intCost) $objCompany = New-Object -TypeName PSObject $objCompany | Add-Member -Name 'Domain' -MemberType Noteproperty -Value "TOTAL UNUSED LICENSES" $objCompany | Add-Member -Name 'Licenses' -MemberType Noteproperty -Value $unusedLicenses $objCompany | Add-Member -Name 'Cost' -MemberType Noteproperty -Value ("{0:C2}" -f $unusedCost) $arrCompany += $objCompany $objCompany = New-Object -TypeName PSObject $objCompany | Add-Member -Name 'Domain' -MemberType Noteproperty -Value "GRAND TOTAL LICENSES" $objCompany | Add-Member -Name 'Licenses' -MemberType Noteproperty -Value $companyLicenses.ActiveUnits $objCompany | Add-Member -Name 'Cost' -MemberType Noteproperty -Value ("{0:C2}" -f ($companyLicenses.ActiveUnits * $intCost)) $arrCompany += $objCompany # Display Statistics $companyLicenses | Format-Table -Auto $arrCompany | Format-Table -Auto