Tag Archives: Administration

Synology VPN L2TP IPSEC

You can install a VPN Server on a Disk Station or Rack Station Synology NAS. When you configure a PPTP setting you can connect from any device without much configuration. However when you want a more secure solution you can choose for L2TP. When you open the correct ports on your router and Synology firewall you can connect from any iOS, Mac OS X, Android and even Windows Phone device. However Windows assumes that you always connect with a direct internet line (so without NAT) to a Internet Server (so without NAT). There is not other configuration. Now in my case I’m mostly behind a NAT device and my Synology most definitely is behind a NAT router. So you have to change some settings in the register and reboot before this works. Microsoft has made a KB for it. In this KB they refer only Vista and Server 2008 as being applicable. But Windows 7, 8, 8.1 , Server 2008 R2, Server 2012 and Server 2012 R2 are also affected. If you configure Windows as specified in the KB you can successfully connect to your Synology.

App-v 5 and Citrix Provisioning

An administrator here came to me and asked me about how to Powershell around a problem with the App-V 5.0 Client Cache directory. The implementation configured is that App-V uses a folder on the D disk. This disk is dedicated. It is not on the distributed Vdisk. When the server reboots the cache becomes corrupted and the App-V service does not start. A sync is necessary in order to start the App-V 5.0 service. I made a script that clears a few reg values, deletes the App-v Client Connection Groups, App-V Client Packages, the AppV folder in Programdata and the entire folder on the D disk.

I handed over the script to the administrator and asked him to create a scheduled task that run at system startup. The reason for  running the script this way, is that creating a GPO that run a Powershell script will not statisfy the required security context. The SYSTEM account doesn’t have enought permissions to complete the script. PSRemoting will not work either. When running the script on another server with the Invoke-Command -Scriptblock {} fails. This is probably due to a bug in App-V. The account has enough rights and UAC is disabled. Yet all attempts fail. Please review the script before implementing

 

<#Script Variables#>
$ServiceName = "AppVClient"
$ProgramDataAppV = "C:\ProgramData\Microsoft\AppV"
$AppVData = "D:\App-V 5.0"

<#Regvalues#>
$Regvalues=@()
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\PackageGroups"}
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\Packages"}
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\Streaming\Packages"}

#Service stoppen om Program Data te verwijderen.
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Remove-Item $ProgramDataAppV -force -recurse

#Verwijderen van de Registersleutels
Foreach ($item in $Regvalues){If ((Test-Path $item.Regvalue) -ne $True){Remove-item $item.regvalue -force -Recurse}}

#Service Starten om initiele synch uit te voeren zodat de D schijf wordt vrijgegeven.
$State = Get-Service $ServiceName
If ($State.status -Match "Stopped"){Start-Service $ServiceName
Start-Sleep -s 5}
Get-AppvPublishingServer | Sync-AppvPublishingServer

#Service Stoppen om Packages en AppvClientConnectionGroup te verwijderen.
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){
Write-Host Stoppen
Stop-Service $ServiceName
Start-Sleep -s 5}
Get-AppvClientConnectionGroup -all | Remove-AppvClientConnectionGroup
Get-AppvClientPackage -all | Remove-AppvClientPackage
Start-Sleep -s 10

#Service stoppen om App-v folder op de D schijf te verwijderen.
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Remove-Item $AppVData -Force -Recurse
Start-Sleep -s 10

#Check of de folder ook daadwerkelijk verwijderd is.
If ((Test-Path $AppVData) -eq $True){

#Proberen de D schijf leeg te krijgen door eerst te synchen
Get-AppvPublishingServer | Sync-AppvPublishingServer
Start-Sleep -s 5
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Get-AppvClientConnectionGroup -all | Remove-AppvClientConnectionGroup
Get-AppvClientPackage -all | Remove-AppvClientPackage
Start-Sleep -s 10
Remove-Item $AppVData -Force -Recurse

#Laatste check op de D schijf om te kijken of de folder nu daadwerkelijk weg is.
If ((Test-Path $AppVData) -eq $True){
$Outinfo = "De App-V Data op de D Schijf is na twee pogingen niet succesvol verwijderd. Bekijk het logboek."
Add-Content -Value $Outinfo -Path "C:\ScriptFout.txt"
$Outinfo = Get-Date
Add-Content -Value $Outinfo -Path "C:\ScriptFout.txt"
}}

#Laatste Sync uitvoeren
Get-AppvPublishingServer | Sync-AppvPublishingServer

Registry permissions of users by mistake overwritten

An administrator applied an GPO which overwrites the permissions on the registry of users by mistake.  This results in users who cannot login after they lost permissions on their ntuser.dat registry hive.

We had an immediate problem with the users so decided to restore the entire terminal profiles share. However you can choose to solve the problem. I’ve written a script really quite to at least know how big the problem really is.

We have PSremoting enabled on all terminal servers. Which gave us the posibility to run the script on the entire environment.

Import-Module ActiveDirectory
$Computers = Get-ADComputer -Filter * | Where {$_.Name -match "TERMINALSERVERPREFIX"}

Foreach ($Computer in $Computers){

Enter-Pssession $Computer
 
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
 Set-Location HKU:
 $list = GCI
 $Hostname = Hostname
 $Export = "C:\Permissions"+"_"+"$Hostname"+".csv"
 Foreach ($item in $list){$ACLs = Get-ACL $Item.PSChildName | Foreach-Object { $_.Access }
 Foreach ($ACL in $ACLs){
 If ($ACL.IdentityReference -match "ADGROUP Or User"){$Value = $Item.Name + ";" + $ACL.IdentityReference + ";" + $ACL.AccessControlType + ";" + $ACL.IsInherited + ";" + $ACL.InheritanceFlags + ";" + $ACL.PropagationFlags + ";" + $ACL.FileSystemRights
 Add-Content -Value $Value -Path $Export}}}
 Set-Location C:
 Copy-Item -Path $Export -Destination "\\Shared Location"

}

This writes back the SID on which an Active Directory Group had permissions on. You can of course use the information given but you have the compare the SID’s with your Active Directory SID.

Exporting the SID’s of your AD can be done by running the following code:

Import-Module ActiveDirectory
$Export = "C:\SIDS.csv"
$List = Get-ADUser -filter * | Select Name,SID
$Header = "Name;SID"
Add-Content -Value $Header -Path $Export
Foreach ($Item in $list){
$Outinfo = $item.Name + ";" + $Item.SID
Add-Content -Value $Outinfo -Path $Export}

Or

Import-Module ActiveDirectory
$Export = "C:\SIDS.csv"
$List = Get-ADUser -filter * | Select Name,SID
$list | Export-CSV -Path $Export -Delimiter ";" -NoTypeInformation 

Users being disconnected randomly

Some users reported that their sessions where being disconnected. The warning that was stated was that the peer disconnected. On the The XenApp servers reported error 4105. The Terminal Server License server was member of the group Terminal Server License Server. There’s a KB article for this problem.

If you want to export the users that could expierence this problem you can run the script below. In order to export the right group you need to have the default SID for this built in group. This SID is: “S-1-5-32-561″. The right value that the user must have is:”5805bc62-bdc9-4428-a5e2-856a0f4c185e”.

 

Import-module ActiveDirectory
$List2 =@()
$File = ".\Export.csv"
$Header = "DN;ActiveDirectoryRights;InheritanceType;ObjectType;InheritedObjectType;ObjectFlags;AccessControlType;IdentityReference;IsInherited;InheritanceFlags;PropagationFlags"
Add-Content -Value $Header -path $file
$list = get-aduser -Filter * | select DistinguishedName
foreach ($item in $list){$list2 +=$item.DistinguishedName}
foreach ($item in $list2){
$ACLs =@((get-Acl "AD:\$item")| ForEach-Object {$_.Access} | Where {$_.Identityreference -eq "S-1-5-32-561"})
IF ($ACLs.count -gt "0"){
[int]$Count = 0
Foreach ($ACL in $ACLS){IF ($ACL.Objecttype -match "5805bc62-bdc9-4428-a5e2-856a0f4c185e"){$count++}}
IF ($Count -eq "0"){
Foreach ($ACL in $ACLs){
$OutInfo = $item  + ";" + $ACL.ActiveDirectoryRights  + ";" + $ACL.InheritanceType + ";" + $ACL.ObjectType + ";" + $ACL.InheritedObjectType + ";" + $ACL.ObjectFlags + ";" + $ACL.AccessControlType  + ";" + $ACL.IdentityReference   + ";" + $ACL.IsInherited   + ";" + $ACL.InheritanceFlags   + ";" + $ACL.PropagationFlags
Add-content -Value $outinfo -path $File}}}}

Sign your scripts

In some high security environments is it required to sign you scripts. To do so you need a code sign certificate. One of the cheapest around is the one of StartSSL costing you only $ 59,99 or roughly € 40 ~ € 45.

I requested a code sign certificate via their site. The advantage of signing scripts with a public certificate is obviously that the script is trusted and you won’t be prompted to approve the script.

To sign a script you need to have the code signing certificate installed and also you need the function Set-AuthenticodeSignature. It is highly recommended that you use a timestamp server. This will ensure that the code is signed when the certificate was valid. So if you certificate expired you won’t have to sign all you code again. StartSSL has a Timestamp Server, but you can use any timestamp server that you prefer. I were at the moment not able to sign my scripts using the StartSSL timestamp server. I use Globalsign at the moment. The certificate from this timestamp server is valid until 2024. If anyone uses your scripts by then, you’d done your job very well ;-).

$Cert=(dir cert:currentuser\my\ -CodeSigningCert)
Set-AuthenticodeSignature ".\Script.ps1" $Cert -IncludeChain All -TimestampServer "http://timestamp.globalsign.com/scripts/timstamp.dll"

Including the chain will ensure that any intermediate certificate authority will be trusted. Be sure to save you code in ANSI format and not the default Unicode:BigEndian that Powershell ISE uses. Notepad(++) will save in ANSI by default. You can use the regular Unicode if you have any diacritic stated.

Your script will be appended with some additional code with certificate information. Note that Powershell v3 will need SHA256 algorithm. Powershell v2 (if anyone still usses that) accepts scripts which are sign with anything up to SHA1. You can specify the algorithm you want to use by entering -HashAlgorithm SHA512. By default in v3 and up it is SHA256.

Manage websites from local server

$list =@(Get-WmiObject -Namespace "root/Webadministration" -Query 'Select * from Site')
Foreach ($item in $list){write-host $item.name}

IIS6 compatiblity uses a different namespace root/MicrosoftIISv2

All you need to do is get cred en authenticate to a different server using either -ComputerName $Hostname or  -Authentication “6”.

Next you can create a remote job using the earlier cached credentials and create a script with the listed names like this:

Import-Module WebAdministration
Stop-Website "$name" 
$State = Get-website |Where {$_.Name -eq "$Name"} | Select State
If ($State -notmatch "Stopped"){Stop-Website $Name }

Of course you can also you the schtasks /create command (in Powershell) to add a job that deletes itself or enable-psremoting.

An entire different approach would be to connect using the servermanager via Powershell. You can load the servermanager and connect to a server. The advantage would be that one server is responsible. You do need access to that server. Some high secure environments block this kind of traffic. You can load any dll for IIS Web Administration

[System.Reflection.Assembly]::LoadFrom( "C:\windows\system32\inetsrv\Microsoft.Web.Administration.dll" )
$computer = "COMPUTERNAME"
$ServerManager = [Microsoft.Web.Administration.ServerManager]::OpenRemote($computer.ToLower())
[int]$ID="1"
Foreach ($item in $ServerManager.sites){
Write-host "$ID $item"
$ID++
}

while ($ID -gt $Servermanager.sites.count){
     $ID = read-host "Voer de site die u wilt stoppen"
      $ID--}


$ServerManager.Sites.Item($ID).stop()

SHA2 certificate OpenSSL Windows

If you have Windows and an OpenSSL installation you can request a SHA256 certificate using the followin code:

set domein=YourDomain
set pass=YourPassword
set organisatie=YourOrganisation
set provincie=YourProviceorState
set stad=YourCity
set string="/CN=%domein%/O=%organisatie%/C=NL/ST=%provincie%/L=%stad%"
echo %string%
openssl genrsa -des3 -passout pass:%pass% 2048 > %domein%.key
openssl rsa -in %domein%.key -passin pass:%pass% -out %domein%-decrypted.key
openssl req –sha256 -new -key %domein%-decrypted.key -subj %string% -out %domein%.csr

Account locked Out Randomly

A user was reporting that at random his AD Account was locked. He ensured me that he did not type his password wrong. After the first six reset I did not believe him. The user was an Administrator so I asked him if by any chance he installed any service under his name. He did change his password some time ago. We decided to revert to his old password. However the problem still occurred. I looked further into the problem. First searching why his account was locked out. On the first domain controller I ran a command:

Get-EventLog -LogName Security | ?{$_.entrytype -eq "FailureAudit" -and $_.message -match "SAMACCOUNTNAMEOFUSER"}

Change the SAMACCOUNTNAMEOFUSER to the sAMAccountname of the user. Add | FL for a larger output of the error.

This retured a set of four result. Three where at the exact same time one was some time after. The message was Kerberos Authentication Failed. The last time was the time that the user came to me saying his account was locked out again.

At the client address was an IP-address specified. It seemed that the Admin had an inactive session on that server or an scheduled task of some sort. Maybe even a service under his account.

I could not enter a pssession to that specific server. So I used a good old DOS Command:

query user /server:IPOFTHATSERVER

It retured the following output:

OutputQueryUser

This  session was logged on far before he changed his password. Maybe this account tried to log on to the domain with an old ticked which caused the DC to lock his account. Maybe he had an open file which occasionally tried to save with old credentials. It did however solve the problem