Wednesday, November 26, 2008

migrate WINS from Windows 2000 Server to 2003

I need to migrate WINS from a Windows 2000 Server to a Windows 2003 Server host.

I. put WINS on the 2003 Server

1. install WINS on the 2003 Server

Start > Control Panel > Add or Remove Programs >

Components > Networking Services > Details

Subcomponents of Networking Services > Windows Internet Name Service (WINS) > OK >

001

Next > Continue >

Finish > Close.

2. point TCP/IP services at this WINS server

Start > Control Panel > Network Connections > Properties >

General > Internet Protocol (TCP/IP) > Properties > Advanced >

WINS > Add >

[put the ip address of the 2003 Server] > Add >

check 'Enable NetBIOS over TCP/IP'

002

OK > Close.

3. check that this WINS Server appears within the WINS service

Start > Programs > Administrative Tools > WINS >

...and the 2003 Server name should appear here:

003

II. copy the WINS database from the Windows 2000 Server host to the Windows Server 2003 host

1. verify that this WINS server is not replicating

on the Windows 2000 Server-based host, open the WINS service and right click the server icon to stop any replication partners:

001

2. stop the WINS service on both servers

Start > Run > type 'cmd' > OK

type 'net stop wins' > ENTER

002

3. copy the WINS files

copy all files in %systemroot%\System32\Wins from the 2000 Server to the same location on the 2003 Server:

003

004

4. restart the WINS service on both servers

Start > Run > type 'cmd' > OK

type 'net start wins' > ENTER

006

III. set up a WINS replication partnership

I have to gradually phase out my old Windows 2000 Server from its WINS responsibilities. Because there are dozens of servers here whose IP settings were manually configured and point to the old server for WINS, I need to set up a replication partnership between the old and new WINS servers. This partnership will need to function until all clients, those receiving DHCP and those that are manually configured, are communicating with the new server.

set up a WINS replication partner in Windows 2000 Server (same for Windows 2003):

Start > Programs > Administrative Tools > WINS >

right-click the 'Replication Partners' node > New Replication Partner... >

enter the IP address of the other WINS server

092

There are 2 areas worth configuring: the push settings and the pull settings. By again right-clicking the 'Replication Partners' node and selecting 'Properties' you can get in to the settings for these 2 items. Push Replication is based on revision number while Pull Replication is based on time. Both are typically used.

093

094

you should see the replication partner appear, here:

095

...and on the Windows 2003 Server, the old WINS server will automatically appear:

092

Settings for Windows Server 2003 are the same as for Windows 2000 Server.

IV. change DHCP scope settings

it's time to point DHCP clients at the new WINS server:

008

009 

see also:

Friday, November 14, 2008

migrate DHCP from Windows 2000 Server to 2003

These are brief instructions. Microsoft has the full-value version, here: How to move a DHCP database from a computer that is running Windows NT Server 4.0, Windows 2000, or Windows Server 2003 to a computer that is running Windows Server 2003. If you're like me, you don't wear a helmet, and you will appreciate my brevity. And actually, I changed a couple things.

One notable difference between me and whoever documents technical procedures for Microsoft is that I work on Earth, for a company, and my implementation must not cause an explosion. We have a bunch of VLANs, managed by Cisco routers, that are configured with the ip helper-address command to ensure DHCP broadcasts are forwarded from clients to the DHCP server. I deviate from Microsoft's generic recommendation for DHCP service migration in this way: I will move one VLAN at a time. This allows me to test things as I go, knowing both servers are handling at least some DHCP scopes, affecting as few clients as possible in the event of catastrophe, and giving myself a clear method for reversing my changes. Also, by adjusting the ip helper-address value on my core routers one VLAN at a time I am able to prevent the new and old DHCP servers from handing out addresses for the same subnet.

I. export the DHCP database from the Windows 2000 Server host

1. stop the DHCP service

command line: net stop dhcpserver

002

2. compact the DHCP data base

command line: cd c:\winnt\system32\dhcp

command line: jetpack dhcp.mdb temp.mdb

004

3. export the database

download, install, and run Microsoft's DHCP Database Export Import Tool (dhcpexim.exe)

006

007

4. restart the DHCP service

command line: net start dhcpserver

009

II. import the DHCP database to the new Windows Server 2003 host

1. install the Windows DHCP component

Start > Control Panel > Add or Remove Programs > Add/Remove Windows Comonents > Netwoking Services >

001

Details >

002

Dynamic Host Configuration Protocol (DHCP) > OK > Next > Finish

2. import the database file

command line: netsh dhcp server import c:\dhcpdb.txt all

003

3. authorize this DHCP server

before authorizing:

004

right-click the server object, then click Authorize

005

III. point the ip helper-address at the new DHCP server

existing configuration, pointing at the old DHCP server:

001

in Cisco IOS, use this command: ip helper-address 172.16.12.12

002

IV. confirm

I set my Vista laptop to retrieve an ip address from a DHCP server and plugged it in to a port on the VLAN we just set up...

001

002

have my laptop send a DHCP request on to this subnet...

command line: ipconfig /renew

004

and confirm on the new DHCP server that this address was handed out by the new server...

008

V. change DHCP lease duration

If you let Windows DHCP do it's own thing, leases will automatically expire after 8 days. But if you want to speed things up, change the DHCP lease duration to something like 2 hours. At least then you'll know sooner if something's broken.

change DHCP lease duration in Windows 2000 Server:

Start > Programs > Administrative Tools > DHCP >

096

expand the server node you're interested in > right click the scope whose lease you want to change > Properties > on the 'General' tab, in the 'Lease duration for DHCP clients' box, check 'Limited to:' and specify a time span

097

VI. turn on DHCP logging

Just in case any clients got left behind, check the DHCP log files for unexpected requests. Do this on the Windows 2000 Server for a couple weeks.

to turn on DHCP logging in Windows 2000 Server:

Start > Programs > Administrative Tools > DHCP >

090

on the 'General' tab, select 'Enable DHCP audit logging'

Windows 2000 will write DHCP log files, one for each day of the week, to this directory: %systemroot%\system32\dhcp

091

093

see also:

Friday, October 31, 2008

kopier, a multi-threaded backup utility in C#

Kopier manages a pool of threads, each thread managing an instance of Robocopy. Some logging and error handling is built in to her as well.

the program class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Mail;

namespace kopier
{
    class Program
    {
        const int maxThreads = 8;

        static void Main(string[] args)
        {
            DateTime startTime;
            int w, c;
            StringBuilder aggMsg = new StringBuilder();

            string[] lines = System.IO.File.ReadAllLines(@args[0]);

            ManualResetEvent[] doneEvents = new ManualResetEvent[lines.Count()];
            kopy[] kopArray = new kopy[lines.Count()];

            ThreadPool.SetMaxThreads(maxThreads, 100);
            ThreadPool.GetMaxThreads(out w, out c);

            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine("kopier");
            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine("Max threads: " + w + ", " + c);
            Console.WriteLine("Launching {0} jobs...", lines.Count());
            startTime = DateTime.Now;
           
            for (int i = 0; i < lines.Count(); i++)
            {
                doneEvents[i] = new ManualResetEvent(false);
                string[] switches = lines[i].Split(new char[]{','});
                string src = switches[0];
                string dst = switches[1];
                TimeSpan min = TimeSpan.FromMinutes(double.Parse(switches[2]));
                kopy k = new kopy(src, dst, min, doneEvents[i]);
                kopArray[i] = k;
                ThreadPool.QueueUserWorkItem(k.threadPoolCallback, i);
            }

            WaitHandle.WaitAll(doneEvents);
            Console.WriteLine("All jobs are complete.");

            aggMsg.Append("started: " + startTime.ToShortTimeString() + ", " + startTime.ToShortDateString() + "\n");
            aggMsg.Append("finished: " + DateTime.Now.ToShortTimeString() + ", " + DateTime.Now.ToShortDateString() + "\n");
            aggMsg.Append("duration: " + DateTime.Now.Subtract(startTime).ToString() + "\r \n");

            for (int i = 0; i < lines.Count(); i++)
            {
                kopy k = kopArray[i];
                Console.WriteLine("job({0}): {1}", k.srcDir, k.kopyMsg);
                aggMsg.Append("job(" + k.srcDir + "): " + k.kopyMsg + "\r \n");
            }

            sendMsg(aggMsg.ToString());
        }

        private static void sendMsg(string msg)
        {
            try
            {
                MailMessage email = new MailMessage();
                email.From = new MailAddress("results@kopy.int");
                email.To.Add(new MailAddress("elijahb@bargain.com"));
                email.Subject = "kopy results";
                email.Body = msg;
                SmtpClient client = new SmtpClient("172.16.12.25");
                client.Send(email);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception during email: {0}", e);
            }
        }
    }
}


the kopy class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;
using System.Diagnostics;

namespace kopier
{
    class kopy
    {
        public kopy(string srcDir, string dstDir, TimeSpan timeMin, ManualResetEvent doneEvent)
        {
            _srcDir = srcDir;
            _dstDir = dstDir;
            _timeMin = timeMin;
            _doneEvent = doneEvent;
        }

        public void threadPoolCallback(object threadContext)
        {
            int threadIndex = (int)threadContext;
            _startTime = DateTime.Now;
 
            Console.Write("job {0} started..." +
                "\n \t job {0} source = " + _srcDir +
                "\n \t job {0} destination = " + _dstDir +
                "\n \t job {0} time limit = " + _timeMin.TotalMinutes.ToString() + " minutes" +
                "\n", threadIndex);
 
            _kopyMsg = kopyAway(_srcDir, _dstDir, _timeMin);

            Console.Write("job {0} finished..." +
                "\n \t job {0} source = " + _srcDir +
                "\n \t job {0} destination = " + _dstDir +
                "\n \t job {0} duration = " + DateTime.Now.Subtract(_startTime).ToString() +
                "\n", threadIndex);

            _doneEvent.Set();
        }

        private string kopyAway(string src, string dst, TimeSpan min)
        {
            string log = dst + @"\rcLog(" + DateTime.Today.ToShortDateString().Replace('/', '-') + ").txt";
            string msg;
            Process p = new Process();

            if (System.IO.Directory.Exists(dst) != true)
            {
                System.IO.Directory.CreateDirectory(dst);
            }

            dst = dst + @"\files";

            try
            {
                p.StartInfo.FileName = "ROBOCOPY";
                p.StartInfo.Arguments = '"' + src + '"' + " " + '"' + dst + '"' + " /MIR /W:10 /R:3 /NP /TEE /LOG+:" + '"' + log + '"';
                p.Start();

                do
                {
                    if (DateTime.Now.Subtract(p.StartTime) >= min)
                    {
                        p.Kill();
                        throw new Exception(buildOutput(src, dst, p.StartTime, DateTime.Now, "Failed: killed for exceeding max time."));
                    }
                    System.Threading.Thread.Sleep(500);
                } while (p.HasExited == false);

                msg = buildOutput(src, dst, p.StartTime, DateTime.Now, "Succeeded.");
            }
            catch (Exception e)
            {
                msg = e.Message.ToString();
            }
            finally
            {
                p.Dispose();
            }
            return msg;
        }

        private string buildOutput(string src, string dst, DateTime startTime, DateTime endTime, string result)
        {  
            return result +
                "\n \t source: " + src +
                "\n \t destination: " + dst +
                "\n \t started: " + startTime.ToShortTimeString() + ", " + startTime.ToShortDateString() +
                "\n \t finished: " + endTime.ToShortTimeString() + ", " + endTime.ToShortDateString() +
                "\n \t duration: " + endTime.Subtract(startTime).ToString();
        }

        public string srcDir { get { return _srcDir; } }
        private string _srcDir;

        public string dstDir { get { return _dstDir; } }
        private string _dstDir;

        public TimeSpan timeMin { get { return _timeMin; } }
        private TimeSpan _timeMin;

        public string kopyMsg { get { return _kopyMsg; } }
        private string _kopyMsg;

        private ManualResetEvent _doneEvent;

        private DateTime _startTime;
    }
}

Thursday, October 23, 2008

setting up IPSec between Windows 2003 and 2000

Following is a procedure to establish IP Security (IPSec) between two Windows Server hosts, one running Server 2003 and the other running 2000 Server. The 2000 Server host is configured to match the more robust default security parameters of Server 2003, while the Server 2003 host is left mostly in a default state. SHA1 is the specified integrity algorithm while packet data is encrypted using 3DES. Both servers require all IP communication between them, but only them, be authentic and encrypted. Traffic from all other sources is not affected by IPSec.

Part I - Configure Windows 2000 Server

1. Create a Console
start > in the run line, type 'mmc' >
ipsec-89
OK >
ipsec-990
In the Console1 window, click 'Console' > Add/Remove Snap-in... >
ipsec-991
Add... > select 'IP Security Policy Management' >
ipsec-992
Add > check next to 'Local Computer' >
ipsec-993
Finish >
ipsec-994
Close >
ipsec-996
OK >
ipsec-01
2. Create a New IP Security Policy
right click on 'IP Security Policies on Local Machine' > Create IP Security Policy >
ipsec-02
Next >
ipsec-03
Next > uncheck 'Activate the default response rule.' >
ipsec-03b
Next > check 'Edit properties' >
ipsec-03c
Finish > check 'Use Add Wizard' >
ipsec-04
Add... >
ipsec-05
Next > check 'This rule does not specify a tunnel' >
ipsec-05a
Next > check 'All network connections' >
ipsec-05b
Next > check 'Use this string to protect the key exchange (preshared key):' > choose a password and type it in the following field >
ipsec-06
Next >
ipsec-05c
3. Create a New IP Filter List for this Security Policy
Add... >
ipsec-07
check 'Use Add Wizard' > Add... >
ipsec-08
Next > select 'My IP Address' from 'Source address:' list >
ipsec-07a
Next > select 'A specific IP Address' from 'Destination address:' list > type SERVER1's IP address in the following field >
ipsec-09
Next > select 'Any' from 'Select a protocol type:' list >
ipsec-08a
Next > uncheck 'Edit Properties' >
ipsec-08b
Finish >
ipsec-08c
Close > select the 'IP Filter List' you just made >
ipsec-09
Next > check 'Use Add Wizard' >
ipsec-09a
4. Create a New Filter Action for this Security Policy
Add... >
ipsec-11
Next >
ipsec-12
Next > check 'Negotiate security' >
ipsec-11a
Next > check 'Do not communicate with computers that do not support IPSec.' >
ipsec-11b
Next > check 'Custom' > Settings... >
ipsec-11c
check 'Data integrity and encryption (ESP):' > select 'SHA1' from 'Integrity algorithm:' list > select '3DES' from 'Encryption algorithm:' list >
ipsec-13
OK >
ipsec-12a
Next >
ipsec-12b
Finish > select the Filter Action you just made >
ipsec-12c
Next > uncheck 'Edit Properties' >
ipsec-12d
Finish >
ipsec-12e
Close >
ipsec-887
right click the IP Security Policy you just made > Assign >
ipsec-888
...and you're done.
5. Test the Configuration
If you're pinging SERVER1 when the security association comes up, you'll see this:
ipsec-90
However, you won't see these replies until both ends are configured. The pings will change from 'Negotiating IP Security' to 'Reply from ...' only after finishing the configuration on SERVER1, the Server 2003 host described in the next section of this document.
Use the built-in IP Security Monitor to verify a successful security association.
Start > type 'ipsecmon'  >
ipsec-995
OK >
ipsec-91
This association will appear only after both ends are configured, both the Windows 2000 Server host discussed above and the Server 2003 host described below.

Part II - Configure Windows Server 2003

1. Create a Console
Start > Run > type 'mmc' >
ipsec-01
OK >
ipsec-02
In the Console1 window, click 'File' > Add/Remove Snap-in... >
ipsec-03
Add... > select 'IP Security Monitor' >
ipsec-04
Add > select 'IP Security Policy Management' >
ipsec-05
Add > select 'Local Computer' >
ipsec-06
Finish >
ipsec-07
Close >
ipsec-08
OK >
ipsec-09
2. Create a New IP Security Policy
right click on 'IP Security Policies on Local Machine' > select 'Create IP Security Policy' >
ipsec-10
Next >
ipsec-11
Next > uncheck 'Activate the default response rule.' >
ipsec-12
Next > check 'Edit properties' >
ipsec-13
Finish > check 'Use Add Wizard' >
ipsec-14
Add... >
ipsec-15
Next > check 'This rule does not specify a tunnel' >
ipsec-16
Next > check 'All network connections' >
ipsec-17
Next >
ipsec-18
3. Create a New IP Filter List for this Security Policy.
Add... > check 'Use Add Wizard' >
ipsec-19
Add... >
ipsec-20
Next > check 'Mirrored. Match packets with the exact opposite source and destination addresses.' >
ipsec-21
Next > select 'My IP Address' from 'Source address:' list >
ipsec-22
Next > select 'A specific IP Address' from 'Destination address:' list > type SERVER2's IP address in the following field >
ipsec-23
Next > select 'Any' from 'Select a protocol type:' list >
ipsec-24
Next > uncheck 'Edit properties' >
ipsec-25
Finish >
ipsec-26
OK > select the 'IP Filter List' you just made >
ipsec-27
Next > select 'Use Add Wizard' >
ipsec-28
4. Create a New Filter Action for this Security Policy
Add... >
ipsec-29
Next >
ipsec-30
Next > check 'Negotiate security' >
ipsec-31
Next > check 'Do not communicate with computers that do not support IPSec.' >
ipsec-32
Next > check 'Custom' >
ipsec-33
Settings... > check 'Data integrity and encryption (ESP):' > select 'SHA1' from 'Integrity algorithm:' list > select '3DES' from Encryption algorithm:' list >
ipsec-34
OK >
ipsec-35
OK >
ipsec-36
Next > uncheck 'Edit properties' >
ipsec-37
Finish > select the Filter Action you just made >
ipsec-38
Next > select 'Use this string to protect the key exchange (preshared key):' > choose a password and type it in the following field >
ipsec-39
Next > uncheck 'Edit properties' >
ipsec-40
Finish >
ipsec-41
OK >
ipsec-42
right click the IP Security Policy you just made > Assign >
ipsec-43
...and you're done.
5. Test the Configuration
You already set up SERVER2 so completing this configuration on SERVER1 will complete both ends of the security association. If you are pinging SERVER2 from SERVER1 as this association comes up, you will see this:
ipsec-90
A successful association should be indicated under the 'IP Security Monitor' node.
ipsec-91
see also: