public/GoldSourceRcon.ps1
<# .SYNOPSIS Performs a Goldsource Rcon. .DESCRIPTION Performs a Goldsource Rcon. .PARAMETER Address DNS or IP address. .PARAMETER Port Port. .PARAMETER Password Rcon password. .PARAMETER Command Rcon command. .EXAMPLE GoldsourceRcon -Address $address -Port $port -Password $rcon_password -Command 'status' .NOTES Goldsource: https://developer.valvesoftware.com/wiki/Goldsource Goldsource Rcon: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Goldsource Rcon python code: https://forums.alliedmods.net/showpost.php?p=1718732&postcount=3 #> function GoldSourceRcon { [CmdletBinding()] param( [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Address , [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [int]$Port , [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Password , [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Command ) try { # Determine the IP $Address = Resolve-DNS -Address $Address Write-Verbose "Sending GoldSourceRcon to $Address`:$Port" $enc = [system.Text.Encoding]::UTF8 # Set up UDP Socket $remoteEP = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Parse($Address), $Port) $udpClient = New-Object System.Net.Sockets.UdpClient $udpClient.Client.SendTimeout = 500 $udpClient.Client.ReceiveTimeout = 500 $udpClient.Connect($remoteEP) function BuildPacket ([string]$Command) { $pack = @(255,255,255,255) + $enc.GetBytes($Command) + 0 $pack } function SendPacket ([byte[]]$pack) { Debug-Packet $MyInvocation.MyCommand.Name $pack $udpClient.Send($pack, $pack.Length) > $null } function ReceivePacket { $pack = $udpClient.Receive([ref]$remoteEP) Debug-Packet $MyInvocation.MyCommand.Name $pack $pack } function GetResponse ([byte[]]$pack) { $response = $enc.GetString( $pack[5..($pack.Length - 1)] ) $response } function Init { # 1 - Client sends: \xFF\xFF\xFF\xFFchallenge rcon\n\0 $pack = BuildPacket "challenge rcon`n" # 2 - Server replies with challenge id $response = SendReceive $pack if ($response -match '(\d+)') { $challengeID = $matches[1] Write-Verbose "Got challengeID: $challengeID" $challengeID } } function SendReceive ([byte[]]$pack) { SendPacket $pack $rPack = ReceivePacket $response = GetResponse $rPack $response } function Debug-Packet ($label, $pack) { if ($pack) { Write-Verbose "[$label]" #Write-Verbose "pack: $pack" Write-Verbose "pack: $( $pack | % { $_.ToString('X2').PadLeft(2) } )" Write-Verbose "pack: " Write-Verbose "$( $pack | % { if ($_ -eq 0x00) { "\".PadLeft(2) } else { [System.Text.Encoding]::Utf8.GetString($_).Trim().PadLeft(2) } } )" Write-Verbose "length: $($pack.Length)" Write-Verbose "" } } # Rcon $challengeID = Init if (!$challengeID) { throw "No challengeID." }else { # 3 - Client sends: \xFF\xFF\xFF\xFFrcon CHALLENGEID RCONPASSWORD COMMAND $pack = BuildPacket "rcon $challengeID $Password $Command" # 4 - Server replies with plain text $response = SendReceive $pack $udpClient.Dispose() if ($response -match 'Bad rcon_password') { throw $response } $response } }catch { if ($ErrorActionPreference -eq 'Stop') { throw }else { Write-Error -ErrorRecord $_ } } } |