FIX: 'Cannot Write Pam Settings' when Joining a Windows Domain in SuSE 10.3

Filed under: Active Directory, Linux, Networking — Written by Chrissy on Saturday, January 19th, 2008 @ 12:29 pm

Today I attacked my 2008 technical to do list and setup a subversion server for backups/source control. It was actually pretty darn easy in SUSE 10.3. After I got it going, I wondered if I could have it automatically authenticate against my HOME domain. So, using SuSE's menu driven interface YaST, I easily added my Linux machine to my Windows domain.

Initially, YaST wasn't able to find or join the domain. This happens sometimes in Windows clients too when:
1. In TCP/IP, the DNS settings are pointed to servers outside of the domain
2. The fully qualified domain name (ex. corp.windomain.com) is not given when joining the domain
3. The FQDN is not listed as a DNS search suffix

After adjuting /etc/resolv.conf to reflect my fully qualified domain name, YaST made it surprisingly easy to find and join the domain. But right as it was finishing up, it ran into the error "cannot write pam settings." I looked around the web and saw about 2 other people had the same problem but no solution was offered. After poking around, I noticed that "pam-smb" was not installed. Generally, SuSE will automatically detect when rpms need to be added but in this case it didn't.

In order to get it all working, I added pam-smb, samba-winbind and krb5-client then I easily plugged into my Windows 2003 domain. Years ago, I tried to do something similar and it seemed to work but I was never able to login via SSH. I'm pretty sure I didn't prefix the domain (in proper case, at that) when attempting to login. Knowing that, I was successfully able to login to my Linux machine using a Windows domain login this time around.

login as: HOME\testuser
Using keyboard-interactive authentication.
Password: *****************
Creating directory '/home/HOME/testuser'.
Creating directory '/home/HOME/testuser/public_html'.
Creating directory '/home/HOME/testuser/bin'.
Creating directory '/home/HOME/testuser/Documents'.
Have a lot of fun...
HOME\testuser@subversion:~>

Awesome! This is much easier than doing user mapping with NIS.

Fix Slow External DNS Resolution in Microsoft/Active Directory DNS Server

Filed under: Active Directory, Networking, Tech Stuff, Windows — Written by Chrissy on Wednesday, April 4th, 2007 @ 12:29 pm

Aw yaille! I just wrote up a whole explanatory blog post then lost it so this one will likely be brief... or not.

Recently, we found that one of our DNS servers was resolving external hostnames unacceptably slow -- about 5 seconds, give or take. The resolution was so slow, in fact, that all of the clients hopped on to the secondary DNS server thinking that the primary had gone down. After logging on to the server to troubleshoot, I could see that:

1. Pinging external hostnames worked well after the hostname resolved. So did traceroute.
2. Caching wasn't working at all
2. Other AD DNS servers on the network were resolving external hostnames quickly
3. The root servers were all there but I deleted and reloaded them anyway
    - Note: you can actually load root servers from a root server which is cool
4. Internal hostname resolution was extremely fast
5. A reboot didn't help (you may laugh but this has solved severe AD problems for me)

Because the other AD Servers were picking up the slack, I decided to come back to it later. I went out and had dinner with a friend then returned after a few hours. Upon logging back on to the Internets, an old network admin friend messaged me. I told him what I was seeing and he said he had the exact same issue a few months back. After a few minutes of trying to recall the solution, he asked "Have you checked your forwarders?" I'd glanced at them but went back to check again. And there it was.. an entry to a machine we'd recently taken down (long story..). I knew the moment I saw the IP that it was the problem. I removed the entry and noticed the forwarded query timeout was equal to *drumroll* 5 seconds.

Finding that solution was impossible on the Internet because of the super general terms: Slow DNS Resolution External Active Directory. Nothing really worked for me so hopefully this post will help others in the future.

VBScript & SQL: Programatically Find the Location of an IP Address

Filed under: Networking, Quick Code, SQL Server, VBScript — Written by Chrissy on Tuesday, January 30th, 2007 @ 7:21 pm

This is more of a post for proper keywords. My previous entry titled "Import MaxMind City CSVs into SQL Server 2005" assumes the user has already conducted research to find that MaxMind's free GeoIP database provides the functionality to look up the location of an IP address. So, if you wish to quickly and easily find an IP address' location, do the following.

1. Ensure you have SQL Server installed somewhere. If you don't currently have it installed,
    you can download SQL Server 2005 Express for free.
2. Read this post about importing the necessary (and free) database for IP lookups.
    a. Download zip & unzip
    b. Read README.txt
    c. Copy the unzip.exe to your Windows directory
    d. Run the included SQL File
    e. Run the included VBS file
3. Create a VBS file to access the information.
4. Double-click the VBS file and enter the IP address

LookupIPAddress.vbs

  strSQLServer = "localhost"
  strDBName = "maxmindGeoIP"
 
  strIPaddr = InputBox("Enter the IP address:","IP To Location")
 
  If Len(strIPaddr) = 0 Then Wscript.Quit
 
  Set objRS = CreateObject("ADODB.recordset")
  strConnstring =  "Driver={SQL Server};Server=" & strSQLServer & ";Database=" & strDBName & ";Trusted_Connection=Yes;"
  strSQL = "EXEC usp_IPtoLocation '" & strIPaddr & "'"
  objRS.Open strSQL, strConnstring, 1, 1
 
  If objRS.eof And objRS.bof Then
    MsgBox "Something is ultra-broken. Is your database populated? " 'Everything should return at least something.
  Else
    strLocation = objRS("location")
      If InStr(strLocation,"Unknown") > 0 Then
      MsgBox "The IP address, " & strIPaddr & ", cannot be found in the database :(",64,"IP To Location"
      Else
      MsgBox  strIPaddr & " resolves to.." & vbCrLf & vbCrLf & objRS("location"),64,"IP To Location"
      End If
   End If
 
   Set objRS = Nothing

Then, finding the location is as easy as double-clicking the file, entering an IP, and pressing "OK"....

In less than 1 millisecond, (after the initial stored procedure execution), your results will show up

MaxMind GeoIP: Import MaxMind City CSVs into SQL Server 2005

Filed under: Networking, Quick Code, SQL Server — Written by Chrissy on Monday, January 29th, 2007 @ 5:45 pm

Inspired by kitty0's GeoIP Demo, I created two scripts which automatically import the free MaxMind GeoIP database (which resolves IP addresses to city locations) into SQL Server using VBS and BCP. The VBS file can be set as a Scheduled Task for MaxMind's free once-a-month updates. I also created a SQL Server UDF to access the data. Resolving the location of an IP is then as easy as running the following query:

SELECT dbo.IPtoLocation('208.65.15.0') as ipLocation (demo)

UDFs, like stored procedures, are pre-compiled and single results, after the intital compilation/first run, are returned in as little as 0.xx milliseconds. I've seen this script process 3000 hostnames a second on a dual proc Macbook (running Windows 2003/SQL 2005) with no load! A huge thanks goes out to Lee Holmes for helping with that. I was so focused on the indexes that I didn't pay attention to the actual data. Once Lee pointed this out, I was able to create a query which query a max of 3000 distinct recs/second as opposed to 6 recs/sec!

Without further ado, you can download the zip of importMaxmindGeoIP files here. This zip includes the following files:
1. importMaxmindGeoIP.sql
2. importMaxmindGeoIP.vbs
3. GNU unzip.exe (and it's license)
4. README.txt

The SQL file creates a database called maxmindGeoIP. It then creates 3 tables, 3 sample UDFs and 3 stored procedures. The database has been indexed as needed and queries have been optimized a ton.

importMaxMindGeoIP.sql

/*
Created by Chrissy LeMaire (clemaire@gmail.com)
Website: http://netnerds.net/
 
! - Run this prior to running importMaxmindGeoIP.vbs - !
 
This script
1. Creates a database named maxmindGeoIP. IF YOU ALREADY HAVE A DB NAMED MAXMINDGEOIP, THIS SCRIPT WILL DROP IT.
2. Creates a 'bcp prep' stored procedure which creates the necessary tables
    - This stored proc is run each time the importMaxmindGeoIP.vbs file is run
3. Creates another bcp related stored procedure which creates the necessary indexes, defrags the indexes and
   shrinks the database. The database is usually about the same size as the CSV (~55MB-65MB as of Jan07)
    - This stored proc is run each time the importMaxmindGeoIP.vbs file is run
4. Creates a few sample stored procedures and user-defined functions
5. Allows guest accounts to connect to and read the db.
6. The bottom of this file contains example usage such as
    -Select '208.65.15.0' as IP,maxmindGeoIP.dbo.IPtoLocation('204.65.15.0') as ipLocation
7. Remember that SQL UDFs and Stored Procedures are pre-compiled so the results will take a little longer the
   first time the function or procedure is run.
 
NO WARRANTIES, USE THIS AT YOUR OWN RISK, etc.
*/
 
On second thought, please just download the rest from the link above (the SQL file or the zip). It's quite long.

The VBS checks the MaxMind site for some zips, downloads them to %TEMP%, unzips to %TEMP%, creates the necessary BCP format files, imports the data and deletes all unnecessary files. It also calls two procedures which prep the database for an import and then cleans up the data and indexes it. This import takes 2-10 minutes to run, depending on a whole lot of variables. Please read the comments section to see the requirements (such as BCP and the login/pass for BCP).

importMaxmindGeoIP.vbs

'****************************************************************************
' Created by Chrissy LeMaire (clemaire@gmail.com)
' Website: http://netnerds.net/
'
' This script downloads the GeoLite CSV files from Maxmind.com
' and uses bcp to transform it into SQL Server data. Run this once
' on the second day of each month.
'
' ! - Run importMaxmindGeoIP.sql prior to running this script - !
' ! - Follow the instructions in README.txt or this won't work - !
'
' 1. You must download "unzip.exe" either from my server at
'     http://blog.netnerds.net/code/importMaxmindGeoIP.zip
'     http://sourceforge.net/projects/gnuwin32 and save it in your
'     PATH (ie. C:\windows)
'
' 2. You must execute the SQL statements found in the zip
'     http://blog.netnerds.net/code/importMaxmindGeoIP.zip prior to running this
'     script
'
' 3. The SQL Script creates a new database called MaxMindGeoIP
'     as well as some stored procs and UDFs. If you change anything
'     in the SQL script, make sure you update the BCP statements
'     below
'
' 4. Run this script on a machine with BCP and a trusted connection to the
'     SQL Server. If you don't have a trusted connection (a domain), change
'     the BCP parameters below (remove -T and add -u,-p).
'
' 5. Run this script at least once from the console. You may be prompted to
'     answer yes to the question "Do you wish to run this program?"
'     for both the vbs file and unzip.exe.  Uncheck the box
'     "Always ask before opening this file" and click "Run"
'
' I have only tested this on SQL Server 2005 and Windows Server 2003
'
' "What it does"
' 1. Downloads the GeoLite CSVs from Maxmind.com to the %TEMP% directory
' 2. Unzips the files into the same directory
' 3. Creates the necessary BCP format files
' 4. Executes bcp to bulk import the file
' 5. Executes a stored procedure which adds indexes to the tables and shrinks the DB.
' 6. Deletes all downloaded/extracted/created files once it's done with them
'
' NO WARRANTIES, USE THIS AT YOUR OWN RISK, etc.
'*****************************************************************************
 
'Meh, please just download this from the link above.

Once the tables are populated, you can do just about anything you'd like with the information. If you'd like to see it in action, click here for a demo on your IP address. The data is capable of returning longitude and latitude so you can also plug this in with Google Maps data (as seen here).

If you'd like this capability for your SQL Server database, download importMaxmindGeoIP.zip, read the README.txt and have fun. Just as an FYI, if you keep track of the IPs that hit your website, here's some sample code

SELECT ipaddr,maxmindgeoip.dbo.IPtoLocation(ipaddr)
FROM hitcounter WHERE dateadded between DATEADD(hh,-24,GETDATE()) and GETDATE()
GROUP BY ipaddr

The GROUP BY basically makes the ipaddr DISTINCT so this shows you where your visitors have come from for the past 24 hours. See the demo which resolves the locations for my last 25 visitors in real time. I also used the script below to query 3000 records a second.

SELECT dbo.iptolocation('24.0.175.222') as ipLocation -- ensure the function runs at least once to compile
GO
SELECT DISTINCT TOP 3000 ipaddr INTO ipaddrs FROM hitcounter -- populate and index a table with 3000 distinct IPs. of course, you need a table with at least 3000 distinct IPs.
GO
CREATE CLUSTERED INDEX IDX_ipaddrs ON dbo.ipaddrs (ipaddr ASC)
GO
DECLARE @startTime datetime
SET @startTime = getDate()
SELECT dbo.iptolocation(ipaddr) from ipaddrs
PRINT 'Your query took '+CAST(DATEDIFF(ms,@startTime,GETDATE()) AS varchar)+' milliseconds to run.'

I can consistently get 1063 and 1050 millisecond runtimes :-D
UPDATE: The original VBS file was set to download the first zip it saw in "http://www.maxmind.com/download/geoip/database/GeoLiteCity_CSV/". I didn't expect Maxmind to keep it archives there but now the updated script looks for the last zip (and presumably the most updated), not the first.

T-SQL UDF: Convert Traditional IP into Numeric IP

Filed under: Networking, Quick Code, SQL Server — Written by Chrissy on Thursday, January 25th, 2007 @ 12:46 pm

This user-defined function (only available in SQL 2000 and above) is part of a larger project I'm working on. PARSENAME in SQL Server is my new favorite function.. Thanks to Jeff Smith for the heads up.

CREATE      FUNCTION [dbo].[IPtoNumeric]  (@strIP varchar(255))
RETURNS bigint
AS
BEGIN
DECLARE @intIPNum bigint
        IF (LEN(@strIP)-LEN(REPLACE(@strIP,'.','')))/LEN('.') = 3   -- check to ensure there are 3 dots
    SET @intIPNum = (16777216 *  CAST(PARSENAME(@strIP,4) as bigint) + 65536 * PARSENAME(@strIP,3) + 256 * PARSENAME(@strIP,2) + PARSENAME(@strIP,1))
RETURN @intIPNum
END

You can quickly test this by issuing the following query:
SELECT dbo.IPtoNumeric('24.0.175.222') as numericIP

VBScript: Use an LDAP Query to Find All Windows Servers on a Domain

Filed under: Active Directory, Networking, Quick Code, VBScript — Written by Chrissy on Tuesday, January 9th, 2007 @ 9:02 pm

Damn, the ADsDSOObject rocks! This script, which weighs in at less than 20 lines, finds all machines running any form of Windows Server on a given domain. Note that this script isn't useful in finding domain controllers, but rather any machine running Windows Server.

Awesome

'****************************************************************************
' This script created by Chrissy LeMaire (clemaire@gmail.com)
' Website: http://netnerds.net/
'
' This script finds all machines running Windows Server (NT, 2000, 2003) in AD
'
'Msgbox output provides server name and OS version.
'
' NO WARRANTIES, USE THIS AT YOUR OWN RISK, etc.
'*****************************************************************************
 
Set objAdRootDSE = GetObject("LDAP://RootDSE")
Set objRS = CreateObject("adodb.recordset")
 
  varConfigNC = objAdRootDSE.Get("defaultNamingContext")
  strConnstring = "Provider=ADsDSOObject"
  strWQL = "SELECT * FROM 'LDAP://" & varConfigNC & "' WHERE objectCategory= 'Computer' and OperatingSystem = 'Windows*Server*'"
  objRS.Open strWQL, strConnstring
    Do until objRS.eof
       Set objServer = GetObject(objRS.Fields.Item(0))
      strServerName = objServer.CN
      strOperatingSystem = objServer.OperatingSystem
      MsgBox strServerName & " is running " & strOperatingSystem
       objRS.movenext
       Set objServer = Nothing
    Loop
  objRS.close
 
Set objRS = Nothing
Set objAdRootDSE = Nothing

Also, I found this nice reference of Command One Liners while searching the web. Totally handy!

Setting Up Bluetooth in Windows Server 2003

Filed under: Networking, Tech Stuff, Windows — Written by Chrissy on Monday, June 5th, 2006 @ 5:44 am

This is a bit recycled from the last post but I'm reframing it so that Googlers can easily find the solution.

I've gotten Bluetooth to work in Windows Server 2k3. Here's are the steps:

  • Download the bt_stack_rtm.exe and extract to a temporary directory. Navigate to that directory and, within the ENU directory, copy Q323183_WXP_SP2_X86_ENU.EXE and place it in C:\. This file the XP SP2 Bluetooth Update
  • Extract the contents by doing the following: Start -> Run -> C:\Q323183_WXP_SP2_X86_ENU.EXE /x
  • Download update.inf and place it in C:\Q323183_WXP_SP2_X86_ENU\update. It basically changes the OS requirements.
  • Download btfiles.zip two files that seem to be missing from the update. Extract them to the C:\Q323183_WXP_SP2_X86_ENU directory.
  • Change directories into C:\Q323183_WXP_SP2_X86_ENU\Update and run update.exe

The ini provided works for Win2k3 R2 (R2 comes with SP1). If it doesn't work for you, you will need to tweak the update.ini file. Double click the ini file and play with the variables NtMinorVersionToUpdate, MaxNtBuildToUpdate, MaxNtMinorVersionToUpdate, MinNtServicePackVersion, MaxNtServicePackVersion, ThisServicePackVersion. Thanks to steeleprice.net for the heads up.

If this all works out for you, you should now see the Bluetooth in your Control Panel. It is listed under "Wireless Link."

TCP/IP Name Resolution Order

Filed under: Networking, Tech Stuff — Written by Chrissy on Tuesday, May 30th, 2006 @ 8:52 pm

I found this gem in Addison Wesley's Inside WIndows Server 2003:

A simple way to remember the order in which TCP/IP uses these tools is the phrase "Can We Buy Large Hard Drives?" The first letters are keys for cache, WINS, Broadcast, Lmhosts, Hosts, and DNS.

Update: I just found the DNS query resolver behavior in the O'reilly book "DNS on Windows Server 2003":

1.The resolver first checks its local cache, which is systemwide (and therefore shared by all applications calling the resolver). If the desired record is not in the cache, the resolver has to send at least one query to a name server.
2. The resolver queries the first name server of the preferred network adapter and waits just one second.
3. If no answer is received, the resolver resends the query simultaneously to the first name server configured for each network adapter and waits two seconds. If the host has only one network adapter, this step is skipped.
4. If no answer is received, the resolver resends the query simultaneously to all name servers configured for all adapters and waits two seconds.
5. If no answer is received, the resolver resends the query simultaneously to all name servers configured for all adapters and waits four seconds.
6. If no answer is received, the resolver resends the query simultaneously to all name servers configured for all adapters and waits eight seconds.
7. If after all this time no name server has returned an answer, the resolver gives up and an error is returned to the application.

Site-to-Site VPN using Windows 2003

Filed under: Networking, Security, Tech Stuff, Windows — Written by Chrissy on Friday, April 28th, 2006 @ 12:44 am

[super old post, reposted]
A few weeks ago, I asked in an IT forum if it was possible to have a "perma-VPN" connection with Windows XP.

After searching for awhile, I found that Microsoft calls perma-VPNs "Demand-Dial Interfaces" and these can only be found in the Windows Server family, not Windows XP.

The best way toget as close to a perma-vpn as possible in XP is to Use Dial Up Networking to login. It initiates the connection for you and you can go about your day. The blinkie icon and actual having to dial in reminded me that this was not a transparent solution..and I really wanted one. So I decided to look into a better solution.

You can use a Windows 2003 server on your network to do WAN dialing using RRAS and Demand Dial Connections. Its incredible easy to setup.

For kicks, I even installed Win2k3 on my laptop (lots of unused licenses at work) and just do a Demand Dial connection to each of the two outside servers. Outlook works like a charm where ever I go.

Here is a quickie view of the topology of my network: (the name of my domain is windomain.com)

Function of Server Physical Location Internal IP (behind firewall) External Hostname
Main Downtown LA 10.0.0.100 dtown.windomain.net
Backup Santa Monica LA 10.0.1.100 sm.windomain.net
Laptop West Hollywood 10.0.2.100 weho.windomain.net

As stated previously, each of the three machines are Windows 2003 servers. I will explain more about the "External Hostnames" in a bit.

The "firewall" is a regular broadband router with VPN Pass-through enabled and port 1723 forwarding to the internal RRAS server.

Because I pay for bandwidth on the Main server, I decided to try to route as little traffic through it as possible. Thus, Laptop maintains two Demand-Dial Interfaces even though I could have actually reached Backup via the WAN link through Main.

Why did I list "External Hostname?" Well, only one server has a truly static hostname and in order for this WAN to work smoothly, hostnames for dial-ins are important. Backup and Laptop are on SoHo DSL lines sotheir IPs change every now and again so I use my internal DNS server to give the external IPs a DNS entry. When their IP changes due to a power outage or firewall reboot, I simply go update the DNS for windomain.net to point to the new IP. Each ofthe servers use my internal DNS server so they don't look for "real" entries of windomain.net, which of course, would not have the sm, weho and dtown entries.

I won't go into extreme detail on how to setup the RRAS but here's a quick idea of what I did to connect Main and Backup

  1. On all three servers, I setup RRAS to support Demand-Dial Interfaces
  2. On Main, I opened the RRAS interface and right clicked on Interfaces then selected "Create new Demand-Dial Interface"
  3. I named the Interface Main2Backup
  4. On the next few prompts, I selected VPN and PPTP
  5. When prompted to enter a hostname for the router to which I am connecting, I typed in sm.windomain.net
  6. I selected Route packets on this interface and create new user account for remote router to dial [back]in
  7. Destination -> Add -> Destination (recall the IP address for Backup/sm above) is 10.0.1.0. Subnet is 255.255.255.0. Metric is left at 1.
  8. NextIwasprompted to create a new user. The username is created from the name of the Interface. In this instance, my username is Main2Backup
  9. Now, I am prompted for the dial-out credentials. Immediately after I am finished with this setup, I will go setup a Demand-Dial Interface on Backup. I know that I will follow the same pattern so the username I will create on Backup/sm will be Backup2Main. I enter this information now.
  10. Finish. Repeat the above steps with slightly different hostname, interface name and dial-in account name on Backup. Eventually, the same will be done on Laptop.

In conclusion, Windows 2003 RRAS provides an awesome and easy solution for setting up WANs without physical router hardware. The process can take as little as a few minutes once appropriate DNS entries have been made.

Good resources for this topic can be found at http://www.microsoft.com/vpn.The whitepaper I used for my setup is found here.

AppleScript: McVPN

Filed under: Networking, Quick Code, Security — Written by Chrissy on Sunday, April 9th, 2006 @ 11:00 pm

This bandaid is mighty handy for pesky OSX disconnects. I don't really know what causes it and unfortunately, I don't have time to fully figure it out. I do know that changing my gateway back to my local gateway helped tremendously. Also, changing my default nameserver to a local nameserver helped too. Now, I get disconnected but its after hours or days instead of minutes.

My system.log referred to lookupd issues and my ping had some sort of buffer problem. That's for you Googlers looking for a solution. Well, here's one...sorta. Throw this in a cron job run by root.

Quick Code

# Author: Chrissy LeMaire
# Copyright 2003 NetNerds Consulting Group
# Script is provided AS IS with no warranties or guarantees and assumes no liabilities.
# Website: http://www.netnerds.net
 
try
    do shell script "date > /applescript/lastRan"
    do shell script "curl --connect-timeout 7 http://webserverOnVPN"
            on error
             do shell script "route flush"
                tell application "Internet Connect"
                set configName to "VPN"
                Disconnect
                end tell
             do shell script "route add default [localGateway]"
                tell application "Internet Connect"
                set configName to "VPN"
                Connect
                end tell
            delay 60
             do shell script "route flush"  -- just changing doesn't work nearly as well
             do shell script "route add default [localGateway]" -- so we flush and readd
             do shell script "route add -net [remoteSubnet] -netmask 255.255.255.0 [localGatway]  -ifp ppp0"
             do shell script "echo "nameserver [localNameserver]" > /etc/resolv.conf"
             do shell script "date >> /applescript/dateLastBroken"
 
end try

This script requires that you have a webserver on the VPN..that's how it checks for a connection. Internet Connect will sometimes report that it's connected when it's not working so this is a better way to tell. It then issues a few commands to change the gateway back to the local one and then rewrites the resolv.conf so that DNS lookups are performed on a local dns server instead of over the VPN.

If I ever have the time figure out how to fix this intead of applying a band-aid, I'll be sure to update this page.