David Hedges

  • Home
  • About
  • Contact
  • Business Blog
  • IT Blog

Backing up Microsoft Exchange to a samba share

January 12, 2021 by dhedges Leave a Comment

Backing up exchange by dumping mailboxes to .pst files can be done using the new-mailboxexportrequest command. This works best though when you script out the process. I have a powershell script I had written, and works for my case:

  Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
 
 Get-MailboxExportRequest -Status Completed | Remove-MailboxExportRequest -Confirm:$false
  Get-MailboxExportRequest -Status failed | Remove-MailboxExportRequest -Confirm:$false
 

get-mailbox | %{New-MailboxExportRequest -Mailbox $($_.id) -FilePath \\SERVER.DOMAIN.local\pst\$($_.samaccountname).pst}

This powershell script is pretty simple. we add in the exchange snaping, kill any export requests that have failed, or previously completed, and may fail. Then export all of the mailboxes.

On the samba host, we are assuming that the server already is bound to the AD domain and allows for local and samba auth through sssd or realm.

When new-mailboxexportrequest exports your mailboxes, it needs rights to allow the “exchange trusted subsystem” to write to the samba share. In addition to this, you need to give rights to the machine account as it initiates the connection as the exchange server machine account.

the following is an example of the share within the samba config that you could use to export pst’s of user mailboxes to.



[pst]
        comment = pst
        valid users = some_user, +domain\"domain admins", xch2019_server\[email protected], +domain\"Exchange Trusted Subsystem"
        read only = no
        path = /mnt/pst
        create mask = 664
        inherit acls = Yes

I Got CryptoLocked

September 29, 2020 by dhedges Leave a Comment

Sunday I got up and was looking for a file I had been working on. Looking through the directory I started noticing a lot of .RZN files. Thinking that was a bit odd, I kept looking, but when I saw them all over, I realized something was very wrong.

First, I thought the only exposed server that was likely susceptible, was a terminal server that was exposed, but I hadn’t been using over the past few months. I jumped over to that server, and saw it too was cryptolocked. with ransom notes all over. I took the server off the network and closed the ports used by it on the firewall.

My file server, I found a suspicious file “4004.exe” and killed and removed it. Initially it looked like I could still pull previous versions, and I had started recovering one of the file systems from the previous version. this only lasted about 5 min, then all of a sudden, all previous versions were removed on every volume. Oh well, I did get some stuff back, but what I got wasn’t really the important stuff.

I moved on to the backup server to see if I could just restore the data from there. upon connecting, this server got hit also, and what made it worse, the ransomware app formatted all the usb disks I had been backing up to. Any chance of a fast recovery was out.

I was glad I also do an online backup, going to that, I found just about everything was backed up to it! After rebuilding a new server, I kicked off a restore from that, fearing that recovery would be slow like the time I had done something similar to restore data to a server in Costa Rica. At least so far I’ve done well. the Costa Rica server took about a month to recover 300G, I’m at a little over 1T recovered in about a day and a half.

Overall, i’m almost back to normal. Though I have some thoughts about it and what I could have done better.

  1. I should have kept the RDP host updated, or just shut it down. Big mistake there.
  2. The other servers that got hit, also should have been updated a bit more often as well.
  3. Though I had good local backups, offsite backup or online backup saved me from total loss or needing to pay the ransom.
  4. I was also thankful that the issue was isolated within a single vlan and didn’t spread to the other networks.

Creating an ISCSI target on RHEL8 / CentOS8

April 13, 2020 by dhedges Leave a Comment

I recently bought a HP server that has 40T of storage outside of the OS array. I had set it up to act as an iscsi storage target for a couple of vmware hosts I run in my lab. Looking around on the internet I was able to find a lot of information on how to create iscsi targets with fileio, but not many that many that talked about utilizing direct access to block storage.

I am going to describe configuring your iscsi target on a block storage device. I am also assuming that you don’t need to open ports in firewalld or have it disabled.

  • locate the device your iscsi storage is on:
    • run: fdisk -l
  • Next install the targetcli package:
    • Run: yum install targetcli -y
  • Run targetcli
  • Create the backstores
    • Run: cd backstores/block
  • Run: create dev=/dev/<storage> name=MyStorage
  • Running “ls” should show something similar to this:
  • Creating the iscsi Targets
    • Run: cd /iscsi
  • Create a iscsi target by creating a custom IQN ( many times the format is iqn.YYYY-MM.com.example:targetdescription )
    • Run: create wwn=iqn.2020-01.com.mydomain:svrstorage
  • Running ls should show something similar to this:
  • Add ACLs for the hosts that will connect
    • Run: cd iqn.2020-10.com.mydomain:svrstorage/tpg1/acls  (using your custome IQN)
    • Create the ACL for the connecting hosts (you must know the IQN of the connecting host)
      • Run: create wwn=iqn.2019-02.com.otherhost:node1
  • Running “ls” should show something like this:
  • We need to map the LUN to the iscsi target
    • Run cd /iscsi/iqn.2020-10.com.mydomain:svrstorage/tpg1/luns  (the IQN being the remote hosts IQN)
    • Run: create /backstores/block/MyStorage
  • Running “ls” should show you something like this
  • Verify it all looks right, and exit
    • Run: cd /
    • Run: ls    and verify that your settings appear correct
  • If all of your devices and ACLs look correct, type exit to save and quit.
  • Start the iscsi target
    • Run: systemctl enable target
      • This will enable the daemon starting each time the server starts up
    • Run: systemctl start target
      • This will start the iscsi target daemon
    • At this point your remote hosts should be able to connect and see the storage you have shared.

How to pull MS Exchange email address into your postfix user-list

June 5, 2018 by dhedges Leave a Comment

I’ve used this in the past to limit the amount of SPAM by only allowing relay back to my exchange server of email addresses that are valid.

in /etc/postfix/main.cf you will need to modify “smtpd_recipient_rectrictions” adding the following. I called my file user-list.

  • “check_recipient_access hash:/etc/postfix/user-list.db”

Adding this will accept mail for email addresses that are listed in the file.

On the Windows Exchange server, for this I’ll assume we are using OWA and we can drop the list of addresses within the inetpub directory, allowing us to pick it up using wget.

On the exchange server I use the following script:

'==================================================================================================
'
' VBScript Source File 
'
' NAME: LISTPROXYADDRESSES.VBS
' VERSION: 0.9
' AUTHOR: Bharat Suneja , Bharat Suneja
' CREATE DATE  : 5/06/2004
' LAST MODIFIED : 9/23/2005
'==================================================================================================
' COMMENT: 
'   
'==================================================================================================

'Set up constant for deleting values from multivalued attribute memberOf

Const ADS_PROPERTY_NOT_FOUND  = &h8000500D
Const ADS_UF_ACCOUNTDISABLE = 2                       'For UserAccountControl
Const strX400Search = "X400"
'______________________________________________________

'Set RootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strDomain = objRootDSE.Get("defaultNamingContext")
strADPath = "LDAP://" & strDomain
'wscript.Echo strADPath
Set objDomain = GetObject(strADPath)
'wscript.echo "objDomain: " & objDomain.distinguishedName

'Setup ADODB connection
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection

'Execute search command to look for Contacts & Groups
    objCommand.CommandText = _
      "<" & strADPath & ">" & ";(&(|(objectClass=contact)(objectClass=group))(mail=*))" & ";distinguishedName,displayName,mail,proxyAddresses;subtree"

    'Execute search to get Recordset
    Set objRecordSet = objCommand.Execute
    
        
        'Start procedure
        
    strResult = strResult & VbCrLf & "Domain: " & strDomain

    strResult = strResult & VbCrlf &  "#Total Records Found (other accounts): " & objRecordSet.RecordCount & VbCrlf
    AddressCount = 0

       While Not objRecordSet.EOF 'Iterate through the search results
 
            strUserDN = objRecordSet.Fields("distinguishedName")     'Get User's distinguished name from Recordset into a string
            set objUser= GetObject("LDAP://"& strUserDN & "")         'Use string to bind to user object
            


                       strResult = strResult & VbCrlf &  "cn: " & objUser.cn
                       strResult = strResult & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult = strResult & VbCrLf & "Proxy Addresses" 
               
                          For Each ProxyAddress in arrProxyAddresses
                          
                            'Sub: Check X400 
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                                     strResult = strResult & VbCrlf &  proxyAddress
                              End If   'Ends loop for X400 address
                Next

            Else
                strResult = strResult & VbCrlf &  "#Object does not have proxy addresses"
            End If
                strResult = strResult &  VbCrLf

     objRecordSet.MoveNext
Wend

'*************************************
'Begin second query for users
varDisabledCounter = 0                  

'Execute search command to look for user
    objCommand.CommandText = _
      "<" & strADPath & ">" & ";(&(objectClass=user)(mail=*))" & ";distinguishedName,displayName,mail,proxyAddresses;subtree"

    'Execute search to get Recordset
    Set objRecordSet = objCommand.Execute
    
    strResult = strResult & vbCrlf &  "#Users"
    strResult = strResult & VbCrlf &  "#Total Records Found (users): " & objRecordSet.RecordCount & VbCrlf
    


       While Not objRecordSet.EOF 'Iterate through the search results
            strUserDN = objRecordSet.Fields("distinguishedName")     'Get User's distinguished name from Recordset into a string
            set objUser= GetObject("LDAP://"& strUserDN & "")         'Use string to bind to user object
            
            
            If objUser.AccountDisabled = TRUE Then                    'If User account disabled, then skip proxy address enum
               varDisabledCounter = varDisabledCounter + 1
               strResult2 = strResult2 & VbCrLf & varDisabledCounter & " " & objUser.displayName & VbCrLf
               
               strResult2 = strResult2 & "cn: " & objUser.cn
                       strResult2 = strResult2 & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult2 = strResult2 & VbCrLf & "Proxy Addresses" 
                       
               
                          For Each ProxyAddress in arrProxyAddresses
                            'Sub: Check X400
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                        		 strResult2 = strResult2 & VbCrlf &  proxyAddress
                                 AddressCount = AddressCount + 1
                              End If   'Ends loop for X400 address
                          Next
                              Else
                                  strResult2 = strResult2 & VbCrLf &  "#Object does not have proxy addresses"
                          End If
                              strResult2 = strResult2 &  VbCrLf
               
               
               
               
               
            Else
            


                       strResult = strResult & VbCrlf &  "cn: " & objUser.cn
                       strResult = strResult & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult = strResult & VbCrLf & "Proxy Addresses" 
                          
                          For Each ProxyAddress in arrProxyAddresses
                            'Sub: Check X400
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                        		 strResult = strResult & VbCrlf &  proxyAddress
                                 AddressCount = AddressCount + 1
                              End If   'Ends loop for X400 address
                          Next
                              Else
                                  strResult = strResult & VbCrLf &  "#Object does not have proxy addresses"
                          End If
                              strResult = strResult &  VbCrLf
                
          End If   'End check for disabled user 
            
     objRecordSet.MoveNext 
Wend  'End second query for users

              
strResult = "Users, Groups & Contacts" & VbCrLf & "-------------------------" & VbCrLf & strResult
strResult = strResult & VbCrLf & "Disabled Users" & VbCrLf & "-------------------------" & VbCrLf & strResult2
'WScript.Echo strResult

'Output to a text file
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile("C:\inetpub\wwwroot\postfix\proxyaddresses.txt")
objOutputFile.Write strResult


     
   


            




You will want to modify the location that it places the file to the correct location for you “Set objOutputFile = objFileSystem.CreateTextFile(“C:\inetpub\wwwroot\postfix\proxyaddresses.txt”)”

After testing this I also created a scheduled task on the exchange server to run this every 15 min. This way when users are added or new email addresses are created they will automatically be placed in a location where they can be picked up by our postfix server.

 

On the postfix server, I created the following script to pull the file from the exchange server and format it correctly for postfix:

 

#!/bin/bash
#pull exhange user email 
#written by David Hedges 

mkdir /tmp/exch-users
cd /tmp/exch-users
wget http://<YOUR SERVER IP or FQDN>/postfix/proxyaddresses.txt

#you may need to add sed statements for other domain extensions if you use one that is not listed
grep -i smtp proxyaddresses.txt |grep -v ADdomain.local |sed 's/smtp://g' |sed 's/SMTP://g'|sed 's/\.com/\.com\tOK/g' |sed 's/\.COM/\.COM\tOK/g' |sed 's/\.net/\.net\tOK/g' |sed 's/\.NET/\.NET\tOK/g' |sed 's/\.tv/\.tv\tOK/g' |sed 's/\.TV/\.TV\tOK/g' |sed 's/\.org/\.org\tOK/g' |sed 's/\.ORG/\.ORG\tOK/g' |sed 's/\.info/\.info\tOK/g' |sed 's/\.INFO/\.INFO\tOK/g' | sed 's/\.us/\.us\tOK/g' | sed 's/\.US/\.US\tOK/g'  >/tmp/exch-users/user-list


/usr/sbin/postmap user-list
mv ./user-list.db /etc/postfix/
mv ./user-list /etc/postfix
cd /tmp
rm -R /tmp/exch-users

This will place both a plain text and a hash file in your /etc/postfix directory.

For this I also created a cron job to run it every 5 min. That way it will pick up the changes as the exchange host publishes them.

Finally, you will need to restart your postfix instance for the change to read the user-list.db file to begin.

 

 

« Previous Page
Next Page »

Copyright © 2025 · Beautiful Pro Theme on Genesis Framework · WordPress · Log in