12 Commits

Author SHA1 Message Date
asif b968fdf93e chore(manifest): bump magicPacket to version 2.0 2021-09-05 18:50:09 -06:00
asif d5c3c071cd refactor(magicpacket): manual MAC address format validation
- use manual format validation for MacAddress so that ErrorAction works
correctly instead of throwing ParameterBindingError which requires
Try/Catch blocks

BREAKING CHANGES:
- remove parameter validation check for MacAddress,
validate while processing
- change all warnings to errors

Closes #1
2021-09-05 18:49:00 -06:00
asif f389999ca3 docs(readme): update with auto-load instructions 2021-09-05 02:13:28 -06:00
asif 1ff4a6bf6a refactor(magicpacket): add manifest and explicit function export 2021-09-05 01:08:20 -06:00
asif cb53f4a7a0 chore(git): update gitignore, add gitattributes 2021-09-04 20:22:46 -06:00
asif 02cd02af1c docs(readme): add table of contents 2021-09-04 19:24:08 -06:00
asif 05fbfe6af4 docs(readme): proofread and update readme 2021-09-04 19:13:23 -06:00
asif f2901b6c80 chore(license): clarify note about creation date 2021-09-04 18:51:40 -06:00
asif 30a5d6fb04 docs(readme): create actual readme 2021-09-04 18:50:38 -06:00
asif 0a9410fb38 docs(magicpacket): update broadcast documentation 2021-09-04 18:50:18 -06:00
asif fea3930b88 chore(license): add author name and creation date 2021-09-04 18:49:54 -06:00
asif bc5dfd8a66 struct: delete sample xml, out of scope for repo
- scope of this repo has been redefined as only cmdlets related to WOL
- this file is inteded for implementation-specific contexts, not
relevant to the cmdlet itself
2021-09-04 18:49:33 -06:00
7 changed files with 348 additions and 31 deletions
+100
View File
@@ -0,0 +1,100 @@
# Common settings that generally should always be used with your language specific settings
# Auto detect text files and perform LF normalization
# https://www.davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
* text=auto
#
# The above will handle all files NOT found below
#
# Documents
*.bibtex text diff=bibtex
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.md text diff=markdown
*.tex text diff=tex
*.adoc text
*.textile text
*.mustache text
*.csv text
*.tab text
*.tsv text
*.txt text
*.sql text
*.ps1 text eol=crlf
# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
# SVG treated as an asset (binary) by default.
*.svg text
# If you want to treat it as binary,
# use the following line instead.
# *.svg binary
*.eps binary
# Scripts
*.bash text eol=lf
*.fish text eol=lf
*.sh text eol=lf
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
*.cmd text eol=crlf
# web frontend stack -- force LF so SRI hashes are always correct
*.html text eol=lf
*.htm text eol=lf
*.css text eol=lf
*.min.css text eol=lf
*.js text eol=lf
*.min.js text eol=lf
*.php text eol=lf
# Visual Studio projects (Rider also)
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Serialisation
*.json text
*.toml text
*.xml text
*.yaml text
*.yml text
# Archives
*.7z binary
*.gz binary
*.tar binary
*.tgz binary
*.zip binary
# Text files where line endings should be preserved
*.patch -text
#
# Exclude files from exporting
#
.gitattributes export-ignore
.gitignore export-ignore
.gitkeep export-ignore
.idea export-ignore
.vscode export-ignore
+71 -9
View File
@@ -1,11 +1,73 @@
# ---> VisualStudioCode ### JetBrains template
.vscode/* # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
!.vscode/settings.json # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code # User-specific stuff
.history/ .idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
+2
View File
@@ -1,3 +1,5 @@
The author of this software, as referred to herein, is Asif Bacchus <asif@asifbacchus.dev>. This software was written on September 3, 2021 and may have been updated since that date without necessarily updating the creation date noted herein.
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
+162 -2
View File
@@ -1,3 +1,163 @@
# ps-cmdlet-wol # PowerShell cmdlet: Send Magic Packet
PowerShell Wake-On-Lan cmdlet. PowerShell cmdlet (module/function) to send a *magic packet* based on provided MAC address(es). Comment-based help is
included in the source-code: `Get-Help Send-MagicPacket -Full`
## Contents
<!-- toc -->
- [Installation and verification](#installation-and-verification)
* [Example: Auto-load for current user](#example-auto-load-for-current-user)
- [Overview](#overview)
- [Broadcast considerations](#broadcast-considerations)
- [Pipeline](#pipeline)
- [Module or Function](#module-or-function)
- [Feedback](#feedback)
<!-- tocstop -->
## Installation and verification
Downloads are available via [my git server](https://git.asifbacchus.dev/asif/ps-cmdlet-wol/releases/latest)
and [GitHub](https://github.com/asifbacchus/ps-cmdlet-wol/releases/latest). You may verify the cmdlet's integrity
using [CodeNotary](https://codenotary.io) via `vcn authenticate` or by dropping the downloaded script and/or manifest
onto their verification webpage at [https://verify.codenotary.io](https://verify.codenotary.io). Please always try to
verify downloaded scripts and software regardless of the source!
If you are integrating this function with your own project or want to manually load the module as needed, then save the
module and manifest file wherever it is convenient for you. If you want to auto-load this function so it is available
automatically in any PowerShell session then you *must* extract it to a directory named **wol-magicPacket** somewhere
defined in your `PSModulePath` depending on your use-case. More information can be found directly from
Microsoft [here](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_modules?view=powershell-7.1#short-description)
.
### Example: Auto-load for current user
Here's a complete example assuming I want the module automatically available for all sessions running under my user
account:
```powershell
# download version 1.1
Invoke-WebRequest -Uri https://git.asifbacchus.dev/asif/ps-cmdlet-wol/archive/v1.1.zip -OutFile "$Env:DOWNLOADS\ps-cmdlet-wol.zip"
# Get PSModulePath
# You should see a user-level modules path in the form of either:
# C:\Users\Username\Documents\WindowsPowerShell\Modules -OR-
# C:\Users\Username\Documents\PowerShell\Modules
$Env:PSModulePath
# change directory to the appropriate path from above
Set-Location "C:\Users\Username\Documents\WindowsPowerShell\Modules"
# extract files and rename directory
Expand-Archive -Path "$Env:DOWNLOADS\ps-cmdlet-wol.zip" -DestinationPath .\
Rename-Item -Path ps-cmdlet-wol -NewName wol-magicPacket
# confirm: you should see a directory named 'wol-magicPacket'
gci
# confirm: you should see the manifest and module within the wol-magicPacket folder
gci .\wol-magicPacket
```
Now, close and re-open PowerShell and the `Send-MagicPacket` function should be available:
```powershell
Get-Command Send-MagicPacket
```
## Overview
The function sends two (2) magic packets spaced one (1) second apart. One set of magic packets will be sent per MAC
address submitted either directly via the `MacAddress` parameter or via the pipeline (implicitly or explicitly). Usage
examples are provided via `Get-Help Send-MagicPacket -Examples`.
The only mandatory parameter is `MacAddress` which can be provided directly or via the pipeline either implicitly or
explicitly (parameter is in the first position). `MacAddress` is an *array of strings*. The actual hex values of the MAC
address can be separated with a colon (':') and/or a hyphen ('-'). For example, the following MAC addresses are all
valid even within the same command:
```powershell
Send-MagicPacket '1a:2b:3c:4d:5e:aa', 'a1-b2-c3-d4-e5-bb', '1a:2b-3c:4d-5e-cc'
```
By default, the magic packet will be sent on the global broadcast address for your current system (e.g. 255.255.255.255)
using UDP on the *echo* port (7). These options can be customized via parameters:
- `-BroadcastIP` | `IP` | `Address`: Broadcast address to use. By default, this is 255.255.255.255 but you really should
use a subnet specific broadcast address instead (e.g. 192.168.1.255). See
the [Broadcast considerations](#broadcast-considerations) section for more discussion.
- `Port`: Allows changing the UDP port over which the magic packet is sent. This is by default port 7 (echo). Port 9 (
discard) is also quite common but any port can be used depending on your particular environment.
The magic packet is constructed as per standards: 6 byte header consisting of '255' (hex:FF) followed by the
hex-represented MAC addresses repeated 16 times.
## Broadcast considerations
Long ago in a galaxy far away... actually a few decades ago right here on Earth, the easiest way to send Wake-On-Lan (
WOL) packets was simply to use the global IP4 all-subnets broadcast address of 255.255.255.255. Because this generates a
lot of un-needed traffic, breaks subnet isolation and can be an attack vector, many routers and switches now block this
type of broadcast. Although this remains the default for most WOL applications (including this function), it is vastly
more reliable and preferred to use a subnet-specific broadcast address. For example, if you are concerned with computers
on your subnet of 192.168.1.0/24 then you would use the broadcast address of 192.168.1.255.
More recently, it has also become somewhat common to use the multicast all-hosts address of **224.0.0.1** when sending
WOL packets. If broadcast is not working in your environment, you may want to try this as a possible workaround.
Things become a little more complicated with IP6. There is no concept of 'broadcast' in IP6 and thus, you need to use
multicast. I have not extensively tested IP6 WOL since I tend to continue using IP4 for this purpose (all my networks
are dual-stack). I would assume the simplest place to start testing would be using the link-local all-nodes address
of **ff02::1**. I suspect this should work across most networks, but I have not tested it extensively and it would
depend greatly on switches, routers and even machine specific set-ups.
## Pipeline
This function is geared toward pipeline usage. The variable `MacAddress` is parameterized and used by the function for
an array of string objects representing individual MAC addresses. This is consistent with WMIC/CIMv2 output for most NIC
queries and allows this function to be easily called using piped output from such a query. To see this, try sending some
dummy magic packets to the localhost for all interfaces on the local machine:
```powershell
# get name, manufacturer and MAC address for connected interfaces and pipe to our function
Get-CimInstance -Query "Select * From Win32_NetworkAdapter Where NetConnectionStatus=2" | Select-Object Name, Manufacturer, MacAddress | Send-MagicPacket -IP 127.0.0.1 -Verbose
```
You will notice I've selected stuff we don't need (Name, Manufacturer) to show that the function can parse and pick up
named the `MacAddress` of each object (network interface) and then send a magic packet to 127.0.0.1 on port 7 (echo).
This is not at all useful, but demonstrates pipeline usage quite nicely, I think. A simpler demonstration would be the
following:
```powershell
# send magic packets to two machines over IP4 localhost using port 9 (discard)
'1a:2b:3c:4d:5e:aa', 'a1:b2:c3:d4:e5:bb' | Send-MagicPacket -BroadcastIP 127.0.0.1 -Port 9
```
## Module or Function
This was intended to be used as a simple function that can be integrated into other scripts directly or, more
conveniently, loaded as a module and referenced as needed in a variety of use-cases.
If using as a function, simply place it within your script. If you want to load it as a module either `Load-Module`
within your script or do so at a PS prompt:
```powershell
# load module
Load-Module C:\path\to\module\wol-magicPacket.psm1
# call module anytime after loading within the same session
Send-MagicPacket ...
```
## Feedback
I coded this pretty quickly for a project I was working on in a small LAN deployment. I also use it routinely in
networks of various sizes and over VPN connections and also when I'm too lazy to move from my office to the living room
to turn on my media centre. I've polished it up and added comment-based help for the version in this repo, hence the
more recent creation date. I'm always interested in improvements since I don't code in PowerShell that often and I'm
sure this can be vastly improved. Please send any suggestions, bugs, etc. to me by filing an issue.
I hope you find this useful! As indicated by the license, you can use this code for whatever you want in any capacity.
If you do use it, a link to my blog at [https://mytechiethoughts.com](https://mytechiethoughts.com) would be greatly
appreciated!
-15
View File
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<db>
<Configuration>
<AlwaysAuthorized>
"ITStaff",
"Administrators",
"Domain Admins"
</AlwaysAuthorized>
</Configuration>
<Computers>
<Computer name="Computer001" mac="AA:1A:2A:3A:4A:01" authorized="any"/>
<Computer name="Computer002" mac="BB:1B:2B:3B:4B:02" authorized="Managers"/>
<Computer name="Computer003" mac="CC:1C:2C:3C:4C:03" authorized="User3"/>
</Computers>
</db>
Binary file not shown.
+12 -4
View File
@@ -11,7 +11,7 @@ Note: You must specify the '-Verbose' parameter to see output for successfully s
Array of MAC addresses for which to construct magic packets. The array should be provided in standard comma-separated string format ('1a:2a:3a:4a:5a:aa', '1b:2b:3b:4b:5b:bb', ...). You may use either a colon (:) or a hyphen (-) to delimit each hex value-pair in the MAC address. You may supply this array either directly or via the pipline. Array of MAC addresses for which to construct magic packets. The array should be provided in standard comma-separated string format ('1a:2a:3a:4a:5a:aa', '1b:2b:3b:4b:5b:bb', ...). You may use either a colon (:) or a hyphen (-) to delimit each hex value-pair in the MAC address. You may supply this array either directly or via the pipline.
.PARAMETER BroadcastIP .PARAMETER BroadcastIP
The address to which magic packets should be sent in order for them to be broadcast across the subnet. By default this is 255.255.255.255 however, many routers block such global broadcasts. Therefore, it is suggested to use the subnet-specific broadcast address (e.g. 192.168.1.255). You may also use IP6 addresses if you prefer. The address to which magic packets should be sent in order for them to be broadcast across the subnet. By default this is 255.255.255.255 however, many routers block such global broadcasts. Therefore, it is suggested to use the subnet-specific broadcast address (e.g. 192.168.1.255). You may also use IP6 multicast addresses (ff02::1 may work in your environment) if you prefer.
.PARAMETER Port .PARAMETER Port
The UDP port that should be used when sending the broadcast. By default this is port 7 (echo). Port 9 (discard) is also a common port. The UDP port that should be used when sending the broadcast. By default this is port 7 (echo). Port 9 (discard) is also a common port.
@@ -50,7 +50,6 @@ function Send-MagicPacket
ValueFromPipelineByPropertyName, ValueFromPipelineByPropertyName,
HelpMessage = "Please provide one or more MAC addresses. You may use a colon (:) or a hypen (-) to separate hex values." HelpMessage = "Please provide one or more MAC addresses. You may use a colon (:) or a hypen (-) to separate hex values."
)] )]
[ValidatePattern('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$')]
[String[]] [String[]]
$MacAddress, $MacAddress,
@@ -83,6 +82,13 @@ function Send-MagicPacket
{ {
foreach ($addr in $MacAddress) foreach ($addr in $MacAddress)
{ {
# validate MAC address format or write error and continue
if (!($addr -match '^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$'))
{
Write-Error "Invalid MAC address: $addr"
continue
}
# convert MAC address to magic packet # convert MAC address to magic packet
try try
{ {
@@ -97,7 +103,7 @@ function Send-MagicPacket
} }
catch catch
{ {
Write-Warning "Unable to process MAC address: $thisMacAddress" Write-Error "Unable to process MAC address: $thisMacAddress"
continue continue
} }
@@ -112,7 +118,7 @@ function Send-MagicPacket
} }
catch catch
{ {
Write-Warning "Unable to send magic packet for '$addr'" Write-Error "Unable to send magic packet for '$addr'"
continue continue
} }
} }
@@ -125,3 +131,5 @@ function Send-MagicPacket
$UdpClient.Dispose() $UdpClient.Dispose()
} }
} }
Export-ModuleMember -Function Send-MagicPacket