<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>netnerds.net</title>
	
	<link>http://blog.netnerds.net</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Fri, 24 May 2013 23:50:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/netnerdsnet" /><feedburner:info uri="netnerdsnet" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>PowerShell Get-WinEvent Bug Workaround on Windows 2008 R2 Server — Importing Windows Forwarded Events into SQL Server using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9U02OZLeGIw/</link>
		<comments>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/#comments</comments>
		<pubDate>Wed, 10 Apr 2013 13:52:49 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2448</guid>
		<description><![CDATA[This is sort of a continuation of my earlier post, Importing Windows Forwarded Events into SQL Server using PowerShell, where I mentioned that I was unable to get the script to work on Windows 2008 R2 due to a known bug in Get-WinEvents. I had to end up deploying my solution to a Windows 2008 [...]]]></description>
			<content:encoded><![CDATA[<p>This is sort of a continuation of my earlier post, <a href=http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/>Importing Windows Forwarded Events into SQL Server using PowerShell</a>, where I mentioned that I was unable to get the script to work on Windows 2008 R2 due to a <a href=http://connectppe.microsoft.com/PowerShell/feedback/details/716533/get-winevent-does-not-return-the-content-of-the-event-message-in-v3-ctp2>known bug</a> in Get-WinEvents. I had to end up deploying my solution to a Windows 2008 R2 Server and was required to write a workaround -- here it is. As always, I prefer using natively available commands, so I eschewed LogParser and used <b>wevtutil.exe</b> instead. </p>
<div class="dirtycodenoclick"><code># Grab events from the last 65 minutes<br />
[xml]$xml = (wevtutil&nbsp;&nbsp;/r:dc qe Application /e:Events)<br />
# build the sql data connection<br />
$connectionString = &quot;Data Source=SQLSERVER;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;Events&quot;<br />
<br />#/q:&quot;*[System[TimeCreated[timediff(@SystemTime) &lt;= 3900000]]]&quot;<br />
# build the datatable<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
$null = $dt.Columns.Add(&quot;ID&quot;)<br />
$null = $dt.Columns.Add(&quot;LevelDisplayName&quot;)<br />
$null = $dt.Columns.Add(&quot;LogName&quot;)<br />
$null = $dt.Columns.Add(&quot;MachineName&quot;)<br />
$null = $dt.Columns.Add(&quot;Message&quot;)<br />
$null = $dt.Columns.Add(&quot;ProviderName&quot;)<br />
$null = $dt.Columns.Add(&quot;RecordID&quot;)<br />
$null = $dt.Columns.Add(&quot;TaskDisplayName&quot;)<br />
$null = $dt.Columns.Add(&quot;TimeCreated&quot;)<br />
<br /># populate data table<br />
$xml.Events.Event | ForEach-Object {<br />
&nbsp;&nbsp; $row = $dt.NewRow()&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventID = $_.System.EventID.&quot;#text&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!$eventID) { $eventID = $_.System.EventID }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;ID&quot;) = $eventID&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventlevel = $_.System.Level<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch ($eventlevel)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 {$eventLevel = &quot;Critical&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 {$eventLevel = &quot;Error&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 {$eventLevel = &quot;Warning&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4 {$eventLevel = &quot;Information&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;LevelDisplayName&quot;) = $eventLevel<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;LogName&quot;) = $_.System.Channel<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;MachineName&quot;) = $_.System.Computer<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;Message&quot;) = $_.RenderingInfo.Message<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;ProviderName&quot;) = $_.System.Provider.Name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;RecordID&quot;) = $_.System.EventRecordID<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;TaskDisplayName&quot;) = $_.RenderingInfo.Task<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;TimeCreated&quot;) =&nbsp;&nbsp;[datetime]$_.System.TimeCreated.SystemTime<br />
&nbsp;&nbsp; $dt.Rows.Add($row)<br />
}<br />
&nbsp;&nbsp;<br />
# Write to the database!<br />
$bulkCopy.WriteToServer($dt)</code></div>
<p><br/><br />
This code imports events from the last 65 minutes. For the initial import, set $xml to <b>wevtutil.exe qe ForwardedEvents /e:Events</b>. As an aside, I was surprised to see that wevtutil is FAR faster than PowerShell's Get-WinEvent, especially during the initial import of a large logs.</p>
<pre>PS C:\Scripts&gt; Measure-Command {c:\scripts\final-getwinevent.ps1}
Days&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0
Hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 1
Seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 19
Milliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 293
Ticks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 792930218
TotalDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0.00091774330787037
TotalHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.0220258393888889
TotalMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 1.32155036333333
TotalSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 79.2930218
TotalMilliseconds : 79293.0218

PS C:\Scripts&gt; Measure-Command {c:\scripts\final-wevtutil.ps1}
Days&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0
Hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 4
Milliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 957
Ticks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 49571333
TotalDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 5.73742280092593E-05
TotalHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.00137698147222222
TotalMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.0826188883333333
TotalSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 4.9571333
TotalMilliseconds : 4957.1333
</pre>
<p><br/><br />
From 79 seconds to 5 for 5500 records! Looks like having to rewrite this was a good thing, after all.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9U02OZLeGIw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Quick and Dirty: Backup SQL Server Express Instances on Enterprise Networks</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/tzvfoopMEvs/</link>
		<comments>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 15:09:00 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2415</guid>
		<description><![CDATA[I know the ideal Enterprise network won't have any SQL Server Express instances, but every large network that I've ever worked on has at least a few. Many times, it's powering apps like SolarWinds or BackupExec. Since SQL Express doesn't run SQL Agent, it can be a pain to backup and maintain the systems. There [...]]]></description>
			<content:encoded><![CDATA[<p>I know the ideal Enterprise network won't have any SQL Server Express instances, but every large network that I've ever worked on has at least a few. Many times, it's powering apps like SolarWinds or BackupExec. Since SQL Express doesn't run SQL Agent, it can be a pain to backup and maintain the systems. </p>
<p>There are a lot of blog posts out there that use PowerShell or some other scheduled script to perform the backups, but it occurred to me the other day that I can totally run all of my backup and maintenance scripts from <b>another SQL Server's SQL Agent</b>. Duh! The key is to use the Connections tab to connect to other SQL instances.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress1.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress1.png" alt="" title="sqlexpress1" width="471" height="254" class="aligncenter size-full wp-image-2423" /></a></p>
<p>I'll be honest, because these servers may come and go and their databases are unpredictable, I don't want to install anything local like <a href=http://ola.hallengren.com/>Ola Hallengren's Backup and Maintenance Scripts</a>, so I setup simple Maintenance Plans with the following parameters:</p>
<ul>
<li>I made one plan with multiple subplans.</li>
<li>Weekly: Full backup, integrity checks, index rebuild, Maintenance cleanup task (4 weeks), History cleanup task (4 weeks)</li>
<li>Daily: Differential, Maintenance cleanup task (4 weeks)</li>
<li>Staggered schedules between server backups -- I don't expect SQL Express databases to take any longer than 30 minutes, so every instance backup is scheduled 30 minutes apart.</li>
<li>The backups go to the same network share as the rest of the SQL instances which kinda look like this: \\sqlbackupserver\backups\HOSTNAME\full, \\sqlbackupserver\backups\HOSTNAME\diff.
<li>No transaction log backups are scheduled -- so far, I haven't found a SQL Express instance with databases that are set to anything but the SIMPLE recovery model.</li>
</ul>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress.png" alt="" title="sqlexpress" width="497" height="383" class="aligncenter size-full wp-image-2416" /></a></p>
<p>Make sure the SQL Server Agent account has adequate access to the SQL Server Express, and that you don't check "Compress backups." Otherwise, your backups will fail with a <small><b>Backup Error: 3041, Severity: 16, State: 1</b></small> error code as SQL Express doesn't support compressed backups.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/tzvfoopMEvs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/</feedburner:origLink></item>
		<item>
		<title>Safely Enable SQL Server Agent MultiServer Administration using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9mm-m2p65dg/</link>
		<comments>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 10:40:18 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2363</guid>
		<description><![CDATA[Update: You can't even independently schedule slave jobs. Count my organization as yet another that won't be implementing MultiServer Administration. Grrr. I always forget about Multiserver Administration. I've actually never worked in an environment that uses it, even though it seems to have a lot of potential. I think one of the biggest reasons is [...]]]></description>
			<content:encoded><![CDATA[<p><b>Update: You can't even independently schedule slave jobs.</b> Count my organization as yet another that won't be implementing MultiServer Administration. Grrr.</p>
<p>I always forget about <a href=http://www.mssqltips.com/sqlservertip/2445/sql-server-multi-server-administration/>Multiserver Administration</a>. I've actually never worked in an environment that uses it, even though it seems to have a lot of potential. I think one of the biggest reasons is that most organizations do not use SSL encryption between SQL Servers, yet out of the box, Multiserver Administration requires SSL encryption for communication between the master and the targets. </p>
<p>Want to change this option? <b>You'll have to modify the registry</b>. Come on, Microsoft: nobody wants to touch a production SQL Server's registry and I think this is the biggest roadblock to mass adoption of Multiserver Administration.</p>
<p>The registry subkey that needs to be changed is <a href=http://msdn.microsoft.com/en-us/library/ms365379.aspx>MsxEncryptChannelOptions</a>. There isn't a whole lot of information about this subkey (such as what other services it impacts) but I'm hoping that since its prefixed with "Msx" that and sits in the SQLAgent key, the change will be isolated to Multiserver Administration. So here are the 3 options:</p>
<table style="border: 1px solid black;" cellpadding=1 cellspacing=1>
<tr>
<td style="border: 1px solid black;">0</td>
<td style="border: 1px solid black;" valign=top>Disables encryption between this target server and the master server. Choose this option only when the channel between the target server and master server is secured by another means.</td>
</tr>
<tr>
<td style="border: 1px solid black;">1</td>
<td valign=top style="border: 1px solid black;">Enables encryption only between this target server and the master server, but no certificate validation is required.</td>
</tr>
<tr>
<td style="border: 1px solid black;">2</td>
<td style="border: 1px solid black;" valign=top>Enables full SSL encryption and certificate validation between this target server and the master server. This setting is the default.</td>
</tr>
</table>
<p><br/></p>
<p>Like the table says, 2 (Encryption+SSL required) is the default. Most blogs I've seen change their option to 0 (No encryption), but I tested it with 1 (Encryption enabled+ SSL not required) and default out of the box SQL encryption settings and it worked. Microsoft says this about the default encryption:</p>
<blockquote><p>Credentials (in the login packet) that are transmitted when a client application connects to SQL Server are always encrypted. SQL Server will use a certificate from a trusted certification authority if available. If a trusted certificate is not installed, SQL Server will generate a self-signed certificate when the instance is started, and use the self-signed certificate to encrypt the credentials.</p></blockquote>
<p>I always prefer encryption if it's not disruptive, so this is the setting I will recommend, and the setting that is default in the script below. This script asks for the SQL Server version (SQL2k5 is not supported because I no longer use it and instance paths are more challenging.) </p>
<div class="dirtycodenoclick"><code>Write-Host &quot;***** Set SQL Agent Encryption Options on Target Servers *****`n &quot;<br />
<br /># Menu for SQL Server Version. SQL Server 2005 could work in theory, but<br />
# it&#039;s registry values are unpredictable and I didn&#039;t want to mess.<br />
<br />[int]$menuChoice = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp; while ( $menuChoice -lt 1 -or $menuChoice -gt 3 ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;1. SQL Server 2008&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;2. SQL Server 2008 R2&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;3. SQL Server 2012&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Int]$menuChoice = read-host &quot;Select your SQL Server version&quot; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
Switch( $menuChoice ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1{$SQLVersion = &quot;10&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2{$SQLVersion = &quot;10_50&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 3{$SQLVersion = &quot;11&quot;}<br />
default{$SQLVersion = &quot;10_50&quot;}<br />
}<br />
<br /># Enter the name of your SQL Server<br />
Write-Host &quot;Enter the hostname of SQL Server (do not include instance name)&quot;<br />
$ServerName = Read-Host &quot;If you are using a cluster, enter the individual node name&quot;<br />
$ServerName = $ServerName.ToUpper()<br />
<br /># And the instance<br />
$Instance = Read-Host &quot;Enter Instance Name (leave blank for default)&quot;<br />
if (!$Instance) {$Instance = &quot;MSSQLSERVER&quot; }<br />
$Instance = $Instance.ToUpper()<br />
<br />Write-Host &quot;`nOptions for Encryption`n&quot;<br />
[int]$menuChoice = -1<br />
&nbsp;&nbsp;&nbsp;&nbsp; while ( $menuChoice -lt 0 -or $menuChoice -gt 2 ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;0. Disables encryption between this target server and the master server.&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;1. Enables encryption only between this target server and the master server, but no certificate validation is required.&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;2. Enables full SSL encryption and certificate validation between this target server and the master server. &quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Int]$menuChoice = read-host &quot;Select Encryption Option for SQL Agent Master/Target Communication&quot; }<br />
Switch( $menuChoice ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; 0{$EncryptionOption = &quot;0&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1{$EncryptionOption = &quot;1&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2{$EncryptionOption = &quot;2&quot;}<br />
default{$EncryptionOption = &quot;1&quot;}<br />
}<br />
<br />$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(&quot;LocalMachine&quot;, $ServerName)<br />
$regKey= $reg.OpenSubKey(&quot;SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL$SQLVersion.$Instance\SQLServerAgent&quot;,$true)<br />
<br />if ($regkey -ne $null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; $oldValue = $regKey.GetValue(&quot;MsxEncryptChannelOptions&quot;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; $regKey.SetValue(&quot;MsxEncryptChannelOptions&quot;,&quot;0000000$EncryptionOption&quot;,[Microsoft.Win32.RegistryValueKind]::DWORD)<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-Host &quot;Done&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; $newValue = $regKey.GetValue(&quot;MsxEncryptChannelOptions&quot;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-Host &quot;Server: $Servername`nOld value: $oldValue`nNew value: $newValue&quot;<br />
} else<br />
{ &quot;No match. Make sure you typed in the proper hostname and instance name.&quot; }</code></div>
<p><br/><br />
(Thanks to <a href=http://quickclix.wordpress.com/2012/08/14/making-powershell-menus/>quickclix</a> for the easy PowerShell menu code.)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/powershell.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/powershell.png" alt="" title="powershell" width="509" height="167" class="aligncenter size-full wp-image-2397" /></a></p>
<p>Once you've run this script and modified the settings on your Target servers, you can easily setup <a href=http://www.mssqltips.com/sqlservertip/2445/sql-server-multi-server-administration/>Multiserver Administration</a>. Note that the default setting may create a SQL Server login for the target server automatically. I uncheck that option because I'm trying to get away from local SQL Server logins and all of my SQL Agents run under the same domain account anyway.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9mm-m2p65dg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Importing Windows Forwarded Events into SQL Server using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/7E_u6Skb7T4/</link>
		<comments>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 16:38:46 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2306</guid>
		<description><![CDATA[Over the past couple weeks, I've looked into a number of ways of parsing and importing Windows Forwarded Events into SQL Server: from using SSIS to LogParser to PowerShell to setting up a linked server to the "Forwarding Events.evtx" file. Ultimately, the only thing that worked was PowerShell's Get-WinEvent cmdlet. And then, it only worked [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past couple weeks, I've looked into a number of ways of parsing and importing <a href=http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/>Windows Forwarded Events</a> into SQL Server: from using SSIS to LogParser to PowerShell to setting up a linked server to the "Forwarding Events.evtx" file. </p>
<p>Ultimately, the only thing that worked was PowerShell's Get-WinEvent cmdlet. And then, it only worked in one specific case for me -- if the events are collected and parsed on a Windows 2012 server. As of today, there's an <a href=http://connectppe.microsoft.com/PowerShell/feedback/details/716533/get-winevent-does-not-return-the-content-of-the-event-message-in-v3-ctp2>unresolved bug</a> in Get-WinEvent that often results in NULL LevelDisplayName, Message, and TaskDisplayName columns. I copied the exact code below on a Win2k8 R2 server and a Win 8 workstation and ran into the NULLs issue repeatedly. Your results may vary, however, as some users have reported success by tweaking a few things in Win2k8 R2 Server.</p>
<p>So, fire up a Windows 2012 box, setup your SQL Server and let's get started:</p>
<h2>The SQL Part</h2>
<p>After looking at the data returned by Get-WinEvent, I found the following columns to be the most useful: ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated. Then I created a table using those columns: </p>
<div class="dirtycodenoclick"><code>CREATE DATABASE EventCollections<br />
GO<br />
USE EventCollections<br />
GO<br />
&#45;- the table name loosely relates to the name of my Win Event Subscription name<br />
CREATE TABLE [dbo].[GeneralEvents](<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Id] [int] NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LevelDisplayName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LogName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [MachineName] [varchar](255) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Message] [varchar](max) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [ProviderName] [varchar](255) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [RecordID] [bigint] NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [TaskDisplayName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [TimeCreated] [smalldatetime] NULL<br />
)<br />
&#45;- Create Unique Clustered Index with IGNORE_DUPE_KEY=ON to avoid duplicates in sqlbulk imports<br />
CREATE UNIQUE CLUSTERED INDEX [ClusteredIndex-EventCombo] ON [dbo].[GeneralEvents]<br />
(<br />
&nbsp;&nbsp;&nbsp;&nbsp; [RecordID] ASC,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [MachineName] ASC,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LogName] ASC<br />
) WITH (IGNORE_DUP_KEY = ON)<br />
GO<br />
</code></div>
<p><br/><br />
In order to avoid duplicates during the hourly imports, I created the table using a unique index with IGNORE_DUP_KEY = ON on 3 columns: RecordID, MachineName and LogName. </p>
<p>Next I had to decide how I'd get the data from PowerShell into SQL Server. After reading up on <a href=http://www.sqlservercentral.com/articles/powershell/65196/>sqlservercentral.com</a> and <a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/28/four-easy-ways-to-import-csv-files-to-sql-server-with-powershell.aspx">technet</a>, I decided on hourly imports using <b>sqlbulkcopy</b>. </p>
<h2>The PowerShell Part</h2>
<p>Forwarded Events are a tricky thing. For some reason, the way that one would usually filter Get-WinEvent results using <a href=http://theboywonder.co.uk/2012/03/15/speeding-up-get-winevent-in-powershell-by-using-filterhashtable/>FilterHasTable</a> kept returning the result <i>Get-WinEvent : No events were found that match the specified selection criteria.</i> I found a number of <a href=http://www.experts-exchange.com/Programming/Languages/Scripting/Powershell/Q_27580312.html>others</a> who ran into this issue, too and similar errors occurred when people attempted to use LogParser. After all that, I didn't have much hope in FilterXML working, but it actually did! So we're going to use that after we perform our initial import.</p>
<p>Here's the code for the <b>initial import</b> which gathers ALL events in Forwarded Events.</p>
<div class="dirtycodenoclick"><code>$events = Get-WinEvent ForwardedEvents |&nbsp;&nbsp;Select-Object ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated&nbsp;&nbsp;<br />
<br />$connectionString = &quot;Data Source=sqlserver;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;GeneralEvents&quot;<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
<br /># build the datatable<br />
$cols = $events | select -first 1 | get-member -MemberType NoteProperty | select -Expand Name<br />
foreach ($col in $cols)&nbsp;&nbsp;{$null = $dt.Columns.Add($col)}<br />
&nbsp;&nbsp;<br />
foreach ($event in $events)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; $row = $dt.NewRow()<br />
&nbsp;&nbsp;&nbsp;&nbsp; foreach ($col in $cols) { $row.Item($col) = $event.$col }<br />
&nbsp;&nbsp;&nbsp;&nbsp; $dt.Rows.Add($row)<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
 # Write to the database!<br />
 $bulkCopy.WriteToServer($dt)</code></div>
<p><br/><br />
You may noticed that I manually built a datatable instead of using <a href="http://gallery.technet.microsoft.com/scriptcenter/4208a159-a52e-4b99-83d4-8048468d29dd">Out-DataTable.ps1</a>, which appears to be a fan favorite. I felt the code above kept things a little more tidy and the performance is still quite good.</p>
<p>Since Event Collection is an on-going thing, you'll likely want to import them on a regular basis. I built the necessary XML query by right clicking on Forwarded Events in Event Viewer -> Filter Current Log... -> Logged: (Change to one hour) -> Click XML tab at top -> Copy/Paste -> Voila.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/savexml.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/savexml-300x114.png" alt="" title="savexml" width="300" height="114" class="aligncenter size-medium wp-image-2292" /></a></p>
<p>Actually, using the syntax of this query, I figured out the syntax for FilterHashTable but having the GUI build my query makes it easy, so I stuck with that. Here is the code for the <b>hourly import</b> that you can setup in Task Scheduler.</p>
<div class="dirtycodenoclick"><code># While this script is intended to run on an hourly basis, the filter is set for going back 65 minutes.<br />
# This allows the script to run for 5 minutes without any missing any events. Because we setup the<br />
# table using the IGNORE_DUPE_KEY = ON, duplicate entries are ignored in the database.<br />
<br />$xml = @&#039;<br />
&lt;QueryList&gt;<br />
&nbsp;&nbsp;&lt;Query Id=&quot;0&quot; Path=&quot;ForwardedEvents&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Select Path=&quot;ForwardedEvents&quot;&gt;*[System[TimeCreated[timediff(@SystemTime) &amp;lt;= 3900000]]]&lt;/Select&gt;<br />
&nbsp;&nbsp;&lt;/Query&gt;<br />
&lt;/QueryList&gt;<br />
&#039;@<br />
<br />$events = Get-WinEvent -FilterXml $xml |&nbsp;&nbsp;Select-Object ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated&nbsp;&nbsp;<br />
<br />$connectionString = &quot;Data Source=sqlserver;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;GeneralEvents&quot;<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
<br /># build the datatable<br />
$cols = $events | select -first 1 | get-member -MemberType NoteProperty | select -Expand Name<br />
foreach ($col in $cols)&nbsp;&nbsp;{$null = $dt.Columns.Add($col)}<br />
&nbsp;&nbsp;<br />
foreach ($event in $events)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; $row = $dt.NewRow()<br />
&nbsp;&nbsp;&nbsp;&nbsp; foreach ($col in $cols) { $row.Item($col) = $event.$col }<br />
&nbsp;&nbsp;&nbsp;&nbsp; $dt.Rows.Add($row)<br />
&nbsp;&nbsp;}</p>
<p># Write to the database!<br />
$bulkCopy.WriteToServer($dt) </code></div>
<p><br/></p>
<p>With any luck, your SQL output should look something like this:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/sqloutput.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/sqloutput.png" alt="" title="sqloutput" width="422" height="146" class="aligncenter size-full wp-image-2354" /></a></p>
<p>Woo.</p>
<p>EDIT: If you care about speed, check out <a href=http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/>this post</a> where I write about using wevtutil instead of Get-WinEvent.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/7E_u6Skb7T4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Centralizing Windows Events using a Collector Initiated Subscription</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/KCU0wCRv6sU/</link>
		<comments>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 14:35:38 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2307</guid>
		<description><![CDATA[So it seems like the best way to go about centralizing Windows Events in an Enterprise is to use GPO, but if you can't or don't want to involve Active Directory GPOs, here's a guide on using one server to go out and collect Windows Events from other servers on your domain. Things you'll need: [...]]]></description>
			<content:encoded><![CDATA[<p>So it seems like the best way to go about centralizing Windows Events in an Enterprise is <a href=http://www.avecto.com/documents/solution-guides/EventCentralization.pdf>to use GPO</a>, but if you can't or don't want to involve Active Directory GPOs, here's a guide on using one server to go out and collect Windows Events from other servers on your domain.</p>
<p>Things you'll need: Windows Server 2012 or 2008 R2, <a href="http://www.windowsecurity.com/articles-tutorials/authentication_and_encryption/Centralized-Auditing-here-FREE.html">the appropriate ports open on your firewall if you're running one</a>, access to a Domain Admin service account or the ability to add a Machine account to a local group on each of the servers you're collecting from.</a></p>
<p>So here's how to setup a Windows 2012 or 2008 R2 Server as the Event Collection Server: first, open up Event Viewer, right click on <b>Forwarded Events</b> and click <b>Properties</b>.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/event1.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/event1.png" alt="" title="event1" width="357" height="413" class="aligncenter size-full wp-image-2256" /></a></p>
<p>Note that Application, Security and System look a bit different than the others. I believe that's because they are considered Classic Windows Events. Classic Windows Events can be easily parsed in PowerShell using Get-EventLog and WMI's Win32_NTEventLogFile but the newer Event Types are a bit trickier. </p>
<p>The first thing you see in the Forwarded Events property tab is this:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/logprops.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/logprops-300x267.png" alt="" title="logprops" width="300" height="267" class="aligncenter size-medium wp-image-2257" /></a></p>
<p>Note the location of the ForwardedEvents.evtx file as it may come in handy for future troubleshooting or archiving. Next, click on the "Subscriptions" tab, then <b>Create</b>. </p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/subproperties.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/subproperties-300x251.png" alt="" title="subproperties" width="300" height="251" class="aligncenter size-medium wp-image-2254" /></a></p>
<p>Now here, I will create just one generic Subscription to capture all Critical and error events. You can create multiple subscriptions for differing criteria and just send all of them to the Forwarded Events log. So select "<b>Collector Initiated</b>" and "<b>Select Computers</b>." Unfortunately, you have to add each server one by one when using the GUI. If you want to add in bulk, you'll likely have to do it using Group Policy and Source Initiation. I haven't found a way to do it in PowerShell yet.</p>
<p>Click <b>Select Events</b> and select what you'd like. My servers are super verbose, and I really only care about Criticals and Errors so I select those two Event Levels, and then By log: Application and System.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/selectevents.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/selectevents-300x300.png" alt="" title="selectevents" width="300" height="300" class="aligncenter size-medium wp-image-2280" /></a></p>
<p>Once you're done with your Event selections, click on <b>Advanced</b> to modify the account you'd like to use as the collector (in my lab, I used a Domain Admin account). </p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/advancedsubs.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/advancedsubs-300x223.png" alt="" title="advancedsubs" width="300" height="223" class="aligncenter size-medium wp-image-2255" /></a></p>
<p>If you use a Machine account or a non-admin, you'll have to go to each of the forwarding servers and add the Computer or User AD account to <b><a href="http://allcomputers.us/windows_7/forwarding-events-(part-2)---how-to-troubleshoot-event-forwarding---how-to-configure-event-forwarding-in-workgroup-environments.aspx">Event Log Readers</a></b>. </p>
<p>Here, you can also configure the Event Delivery Optimization. I left it default for now, though later I do plan to explore delivering Events over HTTPS. Click OK until you're back at Event Viewer. Wait a few minutes and the Events should start coming in. In my experience, for each new computer I setup, I'll get one Information event from the Microsoft-Windows-EventForwarder provider. The event itself is kind of useless, saying "the description for Event 111 cannot be found." but I've learned to accept it's the Event Forwarding confirming there's a new computer in the subscription.</p>
<p>When things get going, your Windows Forwarding collection should look something like this:<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/finalevent.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/finalevent-300x99.png" alt="" title="finalevent" width="300" height="99" class="aligncenter size-medium wp-image-2279" /></a></p>
<p>In this screenshot, I've highlighted Attach Task to Event which allows you to run a program or send an email when the event occurs. Pretty cool.</p>
<p>If you need additional help, Microsoft has a <a href=http://blogs.technet.com/b/wincat/archive/2008/08/11/quick-and-dirty-large-scale-eventing-for-windows.aspx>Quick and Dirty Large Scale Eventing for Windows</a> guide that is good for troubleshooting.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/KCU0wCRv6sU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/</feedburner:origLink></item>
		<item>
		<title>HOW-TO Setup Windows 2012 Server Core Remote Desktop Services to Securely Administer Windows over RDP and SSL</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/qucZwusFg1E/</link>
		<comments>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/#comments</comments>
		<pubDate>Mon, 04 Mar 2013 20:30:06 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[IIS]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2165</guid>
		<description><![CDATA[Alright, so I've wanted to setup a Remote Desktop Gateway for years, but the configuration seemed so.. time-intensive. Then I moved to Belgium, my living situation changed and I didn't want to setup a whole new VPN server to access my virtual lab. Initially, I set up my RD Gateway using too many Remote Desktop [...]]]></description>
			<content:encoded><![CDATA[<p>Alright, so I've wanted to setup a Remote Desktop Gateway for years, but the configuration seemed so.. time-intensive. Then I moved to Belgium, my living situation changed and I didn't want to setup a whole new VPN server to access my virtual lab.</p>
<p>Initially, I set up my RD Gateway using too many Remote Desktop Services: Remote Desktop Connection Broker, Remote Desktop Gateway &#038; Remote Desktop Web Access, but that was because was lead astray by Windows 2012's new GUI. Now, I've narrowed it down <i>only</i> to RD Gateway and I'm even fond of Metro (:O) </p>
<p>So to get this going, all you have to do is install and configure the Remote Desktop Gateway Services (RD Gateway) Role. That seems obvious, but Server Manager's interface which prominently displays an unconfigured "Remote Desktop Services" tab made me think I was missing something.</p>
<p>During the Role installation do: Role-based or feature-based installation -> Remote Desktop Services -> Remote Desktop Gateway<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/rdgateway.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/rdgateway-300x208.png" alt="" title="rdgateway" width="300" height="208" class="aligncenter size-medium wp-image-2167" /></a></p>
<p>Then click Next a bunch of times. Something odd, when it asks you "Do you need an alternate source path?", even if you have the Windows Server 2012 ISO attached, you'll still need to click "Specify an alternate source path" and enter <small><b>D:\sources\sxs</b></small> (assuming your ISO is attached to <b><small>D:</small></b>)</p>
<p>Click Install and wait for the installation to complete. Now it's time to configure RD Gateway. </p>
<p>OPTIONAL: If you're on a domain with a Certificate Authority, you'll want to configure IIS to use a Domain Certificate. Open IIS Manager -> Select your server -> Server Certificates -> Create Domain Certificate. For "Common Name" make sure you enter your <b><small>external FQDN</small></b>. Note: I chose to go with dyndns.org since I have a dynamic IP. It's required that you use an externally resolvable hostname, otherwise Remote Desktop will fail if you try to use an IP or mismatched hosts.</p>
<p>Now, you'll need to configure RD Gateway. Go to Server Manager -> Tasks -> RD Gateway Manager.<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/certarea.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/certarea.png" alt="" title="certarea" width="539" height="161" class="aligncenter size-full wp-image-2174" /></a></p>
<p>Click <i><small>View or modify certificate properties</small></i>. If you don't have a Domain Certificate, just click <i><small>Create and import certificate</small></i> and ensure you use your external FQDN for the certificate name. Otherwise, choose <i><small>Select an existing certificate...</small></i>. Choose your certificate</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/certselect.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/certselect.png" alt="" title="certselect" width="539" height="128" class="aligncenter size-full wp-image-2183" /></a></p>
<p>Click Import -> Apply. Now that you're back at the RD Gateway Manager, expand the tree under your server name. Click Policies then on the right, click Create Authorization Polices for RD Gateway. Create an RD CAP and RD RAP (Recommended). In the name field, you can enter whatever you'd like. I chose "Default" -> Next -> Add Group -> Domain Admins -> (leave Client Computer blank)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/thing.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/thing.png" alt="" title="thing" width="375" height="391" class="aligncenter size-full wp-image-2190" /></a></p>
<p>Next, you'll be given the option to Enable or Disable Device Redirection. I just choose the default (all clients) and click Next -> Next -> Next - Default -> Next -> Allow users to connect to any network resource -> Next -> Allow Connections only to port 3389 -> Next -> Finish</p>
<p>Finally, open up Services and Start Remote Desktop Gateway</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/services.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/services.png" alt="" title="services" width="509" height="103" class="aligncenter size-full wp-image-2193" /></a></p>
<p>Voila! Now you can go modify your router rules to connect port 443 to your RD Gateway Server and/or read the important notes below.</p>
<p><u>A few important things to note</u><br />
As an added security pre-caution, I went into IIS and disabled Anonymous access to my root IIS folder and ensured Windows Authentication was still enabled for the RPC folders.</p>
<p>Configuring the Remote Desktop Client is easy. Open up your Remote Desktop Client -> Advanced -> (Connect from Anywhere) Settings.<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/rdp.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/rdp-287x300.png" alt="" title="rdp" width="287" height="300" class="aligncenter size-medium wp-image-2138" /></a></p>
<p>Enter the external hostname that you entered earlier during the configuration of RD Gateway. Go back to the general tab, and enter the FQDN of the domain server you wish to connect to. Don't worry about resolving the hostname if you're using an external DNS server -- DNS is resolved at the RD Gateway so if the RD Gateway can resolve the hostname, you're set.</p>
<p>If you choose to use a self-signed cert or you are attempting to connect from a computer that's not on the domain, you'll have to import the SSL cert to your Trusted Root Certification Authority. Otherwise, you'll receive the error "This computer can't verify the identity of the RD Gateway 'sample.server.com'. It's not safe to connect to servers that are not identified. Contact your network administrator for assistance." </p>
<p>There are a few ways to do this, but here's how I do it. I use Chrome to hit my server (ex. https://myserver.dyndns.org)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/ssl.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/ssl.png" alt="" title="ssl" width="334" height="261" class="aligncenter size-full wp-image-2145" /></a></p>
<p>Click Certificate Information -> Details -> Copy to File. Save the cert, then find it using Windows Explorer. Right-click on the cert -> Install Certificate -> Place all Certificate in the Following Store -> Trusted Root Certification Authority -> Next -> Finish -> Yes.</p>
<p>You should now be able to connect and securely manage your network, all over SSL <img src='http://blog.netnerds.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/qucZwusFg1E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/</feedburner:origLink></item>
		<item>
		<title>NoMachine NX for OS X Successfully Authenticates But Won’t Load Sessions</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9A3-wgbLT9o/</link>
		<comments>http://blog.netnerds.net/2013/03/nomachine-nx-for-os-x-successfully-authenticates-but-wont-show-sessions/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 13:31:46 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[OS X & iDevices]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2057</guid>
		<description><![CDATA[I recently discovered NoMachine's NX while looking for an easy way to encrypt VNC. NX, if you aren't familiar with it, is generally a PITA to setup, but well worth the pain (on Linux anyway). All traffic goes over SSH and while the performance isn't as great as Windows' RDP, it's faster and more secure [...]]]></description>
			<content:encoded><![CDATA[<p>I recently discovered NoMachine's NX while looking for an easy way to encrypt VNC. NX, if you aren't familiar with it, is generally a PITA to setup, but well worth the pain (on Linux anyway). All traffic goes over SSH and while the performance isn't as great as Windows' RDP, it's faster and more secure than VNC. NoMachine's NX client works on Windows, OS X and Linux and even works well on roaming profiles.</p>
<p>Installing NX Server on OS X is challenging. Well, installing it is easy, getting it to work is another story. </p>
<p>First, starting with Mountain Lion, Apple no longer ships OS X with X11 already installed so XQuartz must be downloaded and installed manually. Initially, I installed XQuartz X11 2.7.4 and NX for OSX 4.0.181-7. </p>
<p>After adding the nx user to my allowed list of SSH logins, connecting was easy using the account I use to login to my MacBook Pro everyday. When prompted for Desktop type, I selected Shadow.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/nx.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/nx-217x300.png" alt="" title="nx" width="217" height="300" class="aligncenter size-medium wp-image-2064" /></a><br />
<br/>Once I connected, my session would appear for a split second then disappear. If you're quick, sometimes you can catch the session before it disappears then click Attach. </p>
<p><center><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/nxviewer.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/nxviewer-300x139.png" alt="" title="nxviewer" width="300" height="139" /></a><br/><small>Oops! Missed it <img src='http://blog.netnerds.net/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </small></center><br />
<br/><br />
<center><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/connected.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/connected-300x139.png" alt="" title="connected" width="300" height="139" /></a><br/><small>Got it!</small></center></p>
<p>Now, initially when I'd attach, it would hang at "Requesting users authorization" but no window would pop up to request the authorization. I checked to ensure that <small><b>PhysicalDesktopAuthorization 0</b></small> was set in <small><b>server.cfg</b></small> and sure enough it was. I thought, then, that maybe there was an issue with xauth. I spent about a day troubleshooting that, and eventually tried a different version of XQuartz. I uninstalled everything across the board. Then reinstalled everything across the board and still no dice. Messing with shadowing in the configs proved fruitless and decided to pour over NX's documentation one last time. This time, I saw that it should have installed the <small><b>nxnode --mirror</b></small> service, but no such service was running.</p>
<p>I created <b><small>/Library/LaunchDaemons/com.nomachine.node.plist</small></b> and pasted the following into it, ensuring that Username was set to my regular user account (otherwise, my session never showed)</p>
<div class="dirtycodenoclick"><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple Computer//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;<br />
&lt;plist version=&quot;1.0&quot;&gt;<br />
&lt;dict&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;Label&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;com.nomachine.node&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;KeepAlive&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;false/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;ProgramArguments&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;array&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;/Applications/NoMachine Service.app/Contents/Frameworks/bin/nxnode&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;&#45;-mirror&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/array&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;UserName&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;chrissylemaire&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;RunAtLoad&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;true/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;StandardErrorPath&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;/Applications/NoMachine Service.app/Contents/Frameworks/var/log/nxnode_stderr.log&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;StandardOutPath&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;/Applications/NoMachine Service.app/Contents/Frameworks/var/log/nxnode_stdout.log&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;WorkingDirectory&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;/Applications/NoMachine Service.app/Contents/Frameworks/bin/&lt;/string&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;Debug&lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;true/&gt;<br />
&lt;/dict&gt;<br />
&lt;/plist&gt;</code></div>
<p><br/><br />
I ran <small>launchctl load -w /Library/LaunchDaemons/com.nomachine.node.plist</small> and voila! My screen appeared. It was ugly and smudgy, though, no matter how well I optimized my client settings. Look:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/blurry1.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/blurry1.png" alt="" title="blurry" width="503" height="530" class="aligncenter size-full wp-image-2088" /></a></p>
<p>Also, it often freezes about 10 seconds after. Seeing that the screen quality wasn't worth it anyway, I decided to go with VNC over SSL until NoMachine NX is out of beta for OS X. Ultimately, I really wanted remote access to manage my virtual Windows farm, so I finally got around to installing and configuring Remote Desktop Gateway. If you're a Windows admin who wants secure Remote Desktop access, you should try Remote Desktop Gateway which does RDP over SSL RPC. It was easy-ish to setup and the quality is just as you'd expect from RDP. Slick!</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9A3-wgbLT9o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/nomachine-nx-for-os-x-successfully-authenticates-but-wont-show-sessions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/nomachine-nx-for-os-x-successfully-authenticates-but-wont-show-sessions/</feedburner:origLink></item>
		<item>
		<title>OS X: launchctl: error unloading</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/x4B7kc0puGs/</link>
		<comments>http://blog.netnerds.net/2013/02/os-x-launchctl-error-unloading/#comments</comments>
		<pubDate>Thu, 28 Feb 2013 15:05:17 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[OS X & iDevices]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2055</guid>
		<description><![CDATA[Need to uninstall xquartz but keep running into the following error? macbook:~ clem$ sudo launchctl unload -w /Library/LaunchAgents/org.macosforge.xquartz.startx.plist launchctl: Error unloading: org.macosforge.xquartz.startx For whatever reason, you have to run this particular unload as a regular user and not as root or using sudo. Once you do that, it should successfully unload.]]></description>
			<content:encoded><![CDATA[<p>Need to uninstall xquartz but keep running into the following error?</p>
<div class="dirtycodenoclick"><code>macbook:~ clem$ sudo launchctl unload -w /Library/LaunchAgents/org.macosforge.xquartz.startx.plist<br />
launchctl: Error unloading: org.macosforge.xquartz.startx</code></div>
<p><br/>For whatever reason, you have to run this particular unload as a <b>regular user</b> and not as root or using sudo. Once you do that, it should successfully unload.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/x4B7kc0puGs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/02/os-x-launchctl-error-unloading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/02/os-x-launchctl-error-unloading/</feedburner:origLink></item>
		<item>
		<title>Leveraging SQL Database Snapshots</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/nBAn9D24loY/</link>
		<comments>http://blog.netnerds.net/2012/08/leveraging-sql-database-snapshots/#comments</comments>
		<pubDate>Thu, 02 Aug 2012 21:18:34 +0000</pubDate>
		<dc:creator>Brandon Abshire</dc:creator>
				<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=1990</guid>
		<description><![CDATA[I've known about SQL Database Snapshots for a while, but never really took the time to use the feature.  Lately, I've gotten into mirroring again and decided to play around with Database Snapshots.  I should clarify at this point that I'm speaking about the native SQL snapshot capabilities, and not a filer technology (such as [...]]]></description>
			<content:encoded><![CDATA[<p>I've known about SQL Database Snapshots for a while, but never really took the time to use the feature.  Lately, I've gotten into mirroring again and decided to play around with Database Snapshots.  I should clarify at this point that I'm speaking about the native SQL snapshot capabilities, and not a filer technology (such as NetApp Snaps).</p>
<p>There are probably many good reasons to use a snapshot, but I'm going to cover three scenarios.</p>
<h5>Application Upgrades</h5>
<p>Often times prior to an application upgrade I am asked to run a full backup for the database.  My typical technique for large databases is to schedule a full backup a bit earlier than the maintenance period and then run a differential backup once the application services have been shut down.  This will dramatically speed up the time it takes to back up the database, while still providing the ability to fail back if the upgrade goes awry.  This has been successful for me in the past, but I decided maybe I should try to take a database snapshot instead and if a fail back is needed, I can restore the database from the snapshot.</p>
<p>I am a little apprehensive to use this method, simply because I'm not comfortable with it.  And since data is so precious (and I'd get fired for losing it), I typically have continued to employ the full/differential backup method.  I will, however, consider in a test environment testing this methodology on databases of various sizes to increase my comfort level.</p>
<p>Assuming you are comfortable with giving it a shot, here's what you would do...<br />
Prior to your application upgrade, once all app services have been shut down and the database is no longer experiencing changes by users, create the database snapshot.<br />
In this example, taken from <a title="MSDN" href="http://msdn.microsoft.com/en-us/library/ms175876.aspx">MSDN</a>, a snapshot is taken of the AdventureWorks database.  The value shown for NAME = &lt;logical_data_file&gt;, is the actual logical data file name of the database you want to make the snapshot from.  This is not a new name for your snapshot.</p>
<div class="dirtycodenoclick"><code>CREATE DATABASE AdventureWorks_dbss1800 ON<br />
( NAME = AdventureWorks_Data, FILENAME =<br />
&#039;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Data\AdventureWorks_data_1800.ss&#039; )<br />
AS SNAPSHOT OF AdventureWorks;<br />
GO</code></div>
<p><br/> Once your snapshot is successful, you can access it from the "Database Snapshots" folder in Management Studio.  It's a point-in-time copy of your database and is created instantly.  Then, once your application upgrade is complete, you can delete it, or restore back to it if necessary.  I have not recovered a large database from a snapshot, but I believe it would be extremely fast as well.  From what I know of snapshots, it maintains pointers to the original data, and when new data blocks are modified, they are written to new blocks on the storage system.  So I assume that restoring from a snapshot will revert the pointers back to that state, allowing for an instant restore.</p>
<div class="dirtycodenoclick"><code>USE master;<br />
&#45;- Reverting AdventureWorks to AdventureWorks_dbss1800<br />
RESTORE DATABASE AdventureWorks from<br />
DATABASE_SNAPSHOT = &#039;AdventureWorks_dbss1800&#039;;<br />
GO</code></div>
<p><br/></p>
<h5>Mirroring</h5>
<p>Another handy way to leverage snapshots is when mirroring.  As you probably know, when you are mirroring a database to another server, the target database on the mirror server cannot be read.  If you need to verify that something made it over, or whatever the circumstance may be, you can create a snapshot of that mirrored database and then query it as a normal database.  Depending on performance impact, you can most likely use this as a reporting server as well if your data does not have to be real-time.</p>
<h5> Nightly Refreshes in a Training Environment</h5>
<p>Many training environments have the desire to revert to a clean state prior to each training session.  The main way to revert may be to set up a SQL Agent job to restore from a flat file, but this is another scenario that I want to restore from a snapshot.  When my training environment is in it's "gold copy" state, I took a flat file backup just to cover my bases.  Then a snapshot.  Instead of setting up a job to overwrite the database from the flat file, I just execute my restore from snapshot command, and the database reverts back.  It's easier and there are less moving parts.</p>
<h5>Things to Consider</h5>
<p>As I stated earlier, from my knowledge of snapshots, a snapshot is just pointers to blocks on a file system.  That's why the snapshot is instant.  The downside to this, however, is that when you query your snapshot, you are hitting the same blocks on the disk as the live database.  If you create too much I/O load against your snapshot, you will also be affecting the live database and can impact performance.</p>
<p>When the live database modifies data, it will write new blocks to the file system.  If your system has a high rate of change and snapshots exist, you will have to account for extra storage.  As new blocks are written, storage usage will increase, even if the database is not actually growing in size.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/nBAn9D24loY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2012/08/leveraging-sql-database-snapshots/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2012/08/leveraging-sql-database-snapshots/</feedburner:origLink></item>
		<item>
		<title>OS X: How to Setup NAT on Lion and Mountain Lion</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/y28zC_24m1k/</link>
		<comments>http://blog.netnerds.net/2012/07/os-x-how-to-setup-nat-on-lion-and-mountain-lion/#comments</comments>
		<pubDate>Sun, 15 Jul 2012 03:33:12 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[OS X & iDevices]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=1823</guid>
		<description><![CDATA[It appears Apple changed the way NAT works, starting in Lion and this upset a lot of people. Apparently, nat would just stop working for some folks after they upgraded to Lion from Snow Leopard. Finding really in-depth information about Apple's NAT implementation is surprisingly hard. While attempting to figure out how to setup a [...]]]></description>
			<content:encoded><![CDATA[<p>It appears Apple changed the way NAT works, starting in Lion and this upset a <a href="https://discussions.apple.com/thread/3293370">lot</a> <a href="https://discussions.apple.com/thread/3198254">of</a> <a href="https://discussions.apple.com/thread/3209267">people</a>. Apparently, nat would just stop working for some folks after they upgraded to Lion from Snow Leopard.</p>
<p>Finding really in-depth information about Apple's NAT implementation is surprisingly hard. While attempting to figure out how to setup a virtual network for two MacBooks connected to one another over Ethernet, I found a few helpful resources, but none helped me understand <em>exactly</em> how OS X does natd within InternetSharing and no matter whose blog or tutorial I followed, I just couldn't get /usr/sbin/natd to forward my packets. This is how my setup first looked...</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2012/07/bigsetup.png" target="new"><img src="http://blog.netnerds.net/wp-content/uploads/2012/07/nat.png" alt="" title="nat" width="512" height="221" class="aligncenter size-full wp-image-1928" style="border: 0px" /></a></p>
<p>I experimented with VLANs, bridges, routing tables, Parallels NAT, Apple NAT, InternetSharing, ipfw, config files and other stuff I've forgotten. I typed in <strong><small>netstat -nr|more</small></strong> and <strong><small>ifconfig</small></strong> more times than I can count. One thing I didn't get into was pf, though. It looked a little too complex.</p>
<p>First, the reason(s) why I didn't want to use Apple's InternetSharing app even though while using it, the VMs on both MacBooks could ping one another and the Internet. I'm a control freak. I want to manage my own everything. My own DNS, my own DHCP server and I want to pick my own damn subnet. Apple <em>says </em>that <a href="https://developer.apple.com/library/mac/#documentation/Darwin/Reference/Manpages/10.6/man8/InternetSharing.8.html">you can change the subnet</a> by modifying <a href="http://krypted.com/mac-os-x/change-subnet-with-internet-sharing-on-os-x/">SharingNumberStart</a> in the nat defaults file but this won't work if you already have any device assigned to an IP in that subnet. To avoid conflicts, InternetSharing takes it upon itself to modify the subnet by one octet (172.20.0.1 -&gt; 172.20.1.1) which is the opposite of what I want. I was also unable to find any documentation on how to modify the subnet mask, so I don't even think that's possible with InternetSharing.</p>
<p>My network requirements aren't that common, admittedly. It's not often that someone will want to hook up two MacBook Pros and run a lil virtual network between them using only an Ethernet cable but, eh, I do. Btw, did you know that you don't need a <a href="http://support.apple.com/kb/TA25550?viewlocale=en_US">crossover cable</a> for MacBooks to talk to one another directly over gigabit Ethernet? Me either. Anyway, I didn't want to buy a gigabit router because this is a very short term project. And I thought I'd enjoy the challenge of figuring this out.</p>
<p>I knew my nat configs were mostly right, I was just missing something with the routes. I finally found the last piece using <strong>route monitor</strong> and watching what InternetSharing changed when it was turned on and all client VMs could ping each other and the Internet(s).</p>
<p>Check out the routing table InternetSharing created:</p>
<p><center><a href="http://blog.netnerds.net/wp-content/uploads/2012/07/Screen-Shot-2012-07-12-at-11.09.17-PM.png"><img class="alignnone size-full wp-image-1844" title="Screen Shot 2012-07-12 at 11.09.17 PM" src="http://blog.netnerds.net/wp-content/uploads/2012/07/Screen-Shot-2012-07-12-at-11.09.17-PM.png" alt="" width="540"/></a></center></p>
<p>192.168.1.1 is my Wireless connection, 192.168.2.1 is Apple's NAT subnet and the other nets were created by Parallels. Most network admins I talked to immediately thought the multiple gateways were causing an issue but this is the setup that actually <em>worked</em>, it just wasn't customizable enough. By the way, BSD has one of the few tcp/ip stacks that allow you to have multiple gateways (so I read.)</p>
<p>So after about a week of prodding, I figured out that this is what Apple <strong><small>basically</small></strong> does within InternetSharing:
<div class="dirtycodenoclick"><code>gwdev=en1<br />
ifconfig bridge0 create<br />
ifconfig bridge0 up<br />
ifconfig bridge0 addm en0<br />
ifconfig bridge0 172.20.0.1<br />
route add default -interface bridge0 -ifscope bridge0 -cloning<br />
sysctl -w net.inet.ip.forwarding=1<br />
/sbin/ipfw add 100 divert natd ip from any to any via $gwdev<br />
/usr/sbin/natd -interface $gwdev -use_sockets -same_ports -unregistered_only -dynamic -clamp_mss -enable_natportmap -natportmap_interface en0</code></div>
<p><br/> That and a bunch of error handling and things related to DHCP and DNS. It also checks to see if the Internet connection exists and deletes the nat/bridge if it doesn't and recreates it when the connection is back up.</p>
<p>Here's a visual of my network after running that script:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2012/07/natsetup.png" target="new"><img src="http://blog.netnerds.net/wp-content/uploads/2012/07/natsetup.png" alt="" title="medconfig" width="540" class="aligncenter size-full wp-image-1938" style="border: 0px" /></a><br />
I need to start working on my project so further error handling and automation are going to be dealt with later.</p>
<p>Below is the code I've started using on my machine. My guest OS network runs a Windows domain and has its own DNS and DHCP servers so those are not addressed in this script. They are really important services, though so if you don't have them setup, <a href="http://support.apple.com/kb/HT5215">you'll want to do that</a>.</p>
<p>Oh, it also doesn't make any changes to the firewall except to add a forwarding rule. You'll want to setup your firewall, too. Annnd this script doesn't use a specific network interface. I make it detect the current gateway then use that interface. If it can't find a gateway, it uses en1. I should probably make it just die but whatever.</p>
<div class="dirtycodenoclick"><code>#!/bin/bash<br />
<br /># Get the interface name for the gateway<br />
gwdev=`netstat -nr | grep default | awk &#039;{ print $6 }&#039; | head -1`<br />
<br /># If none are found, set the gateway to en1 (generally Wifi on OS X)<br />
if [ -z &quot;$gwdev&quot; ]; then<br />
gwdev=en1<br />
fi<br />
<br /># Create a bridge, add the Ethernet device<br />
ifconfig bridge0 create<br />
ifconfig bridge0 up<br />
ifconfig bridge0 addm en0<br />
# Give it an IP, route bridge0&#039;s traffic to bridge0<br />
ifconfig bridge0 172.20.0.1<br />
route add default -interface bridge0 -ifscope bridge0 -cloning<br />
<br /># Enable IP forwarding, add a firewall rule to send all natd traffic to the real gateway<br />
# Start natd with a whole bunch of options<br />
sysctl -w net.inet.ip.forwarding=1<br />
/sbin/ipfw add 100 divert natd ip from any to any via $gwdev<br />
/usr/sbin/natd -interface $gwdev -use_sockets -same_ports -unregistered_only -dynamic -clamp_mss -enable_natportmap -natportmap_interface en0</code></div>
<p><br/>And to stop... </p>
<div class="dirtycodenoclick"><code>#!/bin/bash<br />
# All these steps look excessive but address<br />
# network instability issues created by not doing them<br />
<br />gwdev=`netstat -nr | grep default | awk &#039;{ print $6 }&#039; | head -1`<br />
<br />if [ -z &quot;$gwdev&quot; ]; then<br />
gwdev=en1<br />
fi<br />
<br />killall natd<br />
/sbin/ipfw delete 100 divert natd ip from any to any via $gwdev<br />
sysctl -w net.inet.ip.forwarding=0<br />
ifconfig $gwdev down<br />
ifconfig en0 down<br />
route delete default -interface bridge0 -ifscope bridge0<br />
ifconfig bridge0 172.20.0.1 delete<br />
ifconfig bridge0 deletem en0<br />
ifconfig bridge0 destroy<br />
ifconfig en0 up<br />
ifconfig $gwdev up</code></div>
<p>One big important thing for laptop users is that natd becomes unstable after the laptop wakes from sleep. To address that, I created the scripts above, installed sleepwatcher, and set sleepwatcher to run /sbin/stopnat on sleep and /sbin/startnat it on wake. This makes natd run 24/7 so make sure that's what you want. I also need to put it in the startup but haven't yet.</p>
<p>Here's that setup, real quick:<br />
<strong><small>sudo port install sleepwatcher<br />
/usr/local/sbin/sleepwatcher -d --wakeup /sbin/startnat --sleep /sbin/stopnat</small></strong></p>
<p>It's likely I'll keep develop this more over time, but for now, my clusters need my attention. I know it's a bit of a pain just copy/pasting so give me about a month or eight and I'll package up the files nice and put em up here.</p>
<p>Update: If you're looking to do this without NAT, check out Thomas' post about <a href="http://maybeageek.wordpress.com/2013/01/30/bridging-ethernet-interfaces-under-os-x/" title="bridging ethernet interfaces in OS X" target="_blank">bridging ethernet interfaces in OS X</a>.</p>
<p>References: <a href="http://help.apple.com/advancedserveradmin/mac/10.7/">OS X Advanced Server Guide</a>, <a href="http://www.amazon.com/Mac-OS-Unix-Geeks-Leopard/dp/059652062X">Mac OS X for Unix Geeks</a>, a blog post by <a href="http://akutz.wordpress.com/2009/08/20/building-a-better-os-x-firewall-or-how-i-solved-the-nat-problem-for-virtualbox/">akutz</a> and every support forum for OSX, FreeBSD and Parallels ever.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/y28zC_24m1k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2012/07/os-x-how-to-setup-nat-on-lion-and-mountain-lion/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2012/07/os-x-how-to-setup-nat-on-lion-and-mountain-lion/</feedburner:origLink></item>
	</channel>
</rss>
