netnerds.net

2Oct/093

Securing Subversion with Windows 2008 Kerberos-Based SSO and Linux-Based Apache

Some things just belong on Linux. Like Subversion and Apache, for instance. I've seen the ghetto workarounds for Windows-based Apache installs and no thanks -- I'd much rather waste my time on ghetto SharePoint workarounds.

But I sure do like the way Windows-based web servers such as IIS seamlessly and securely authenticate users across a domain. I wanted Apache to do the same and, after a week of trying various methods of authentication, I found the easiest, most efficient way is to use SSL, Kerberos, and Likewise.

I start this project, as I do all of my Linux projects, by using a fresh install of SuSE Linux Enterprise Server (SLES 11). During the initial install, I made sure to use a local passwd file for authentication. Likewise takes care of all the advanced authentication methods after the install is complete. When using Likewise, do not attempt to use YaST to configure authentication or you'll run into a variety of pam and krb5 key issues.

Here are the following steps and tutorials I used to accomplish my goal of SSO

  1. Install and configure Likewise Open.
    • Joining a domain is as easy as /opt/likewise/bin/domainjoin-cli join corp.netnerds.net Administrator, even when authenticating against Windows 2008 Active Directory.
  2. Setup Apache to support SSL
  3. Setup Apache to support Kerberos-based SSO
    • My ktpass, for example, looks like this:
      ktpass /out http.ktb /princ HTTP/ariel.corp.netnerds.net@CORP.NETNERDS.NET /pass SkiAlta2009 /mapuser corp\linuxweb
  4. Install the One-Click Installer that comes with OpenSuSE by default, but not SLES 11.
    • yast -i yast2-metapackage-handler
  5. Add the subversion packages to the local repository.
    • OCICLI http://software.opensuse.org/ymp/Subversion/SLE_11/subversion.ymp
    • Go into YaST and install the necessary subversion packages.
  6. Follow the OpenSuSE tutorial for Setting Up a Subversion Server Using Aapache 2
  7. Throw a party! Just turn up Pandora's Cajun station and DANCE.

I recommend using your domain's own Certificate Authority to generate the SSL cert that Apache will use. That way, users won't be prompted to accept an untrusted self-signed SSL certificate.

Have fun!

Posted by: Chrissy   Filed under: Active Directory, Apache, Linux, Networking, Security 3 Comments
1Oct/094

SuSE (SLES) 11 Works Flawlessly with Windows Server 2008 Authentication

Well that couldn't have been easier! Here's all it takes to authenticate SLES 11 to Windows Server 2008 based Active Directory. During the initial install of SLES, I performed the following:

  • Selected samba-client and winbind during the software installer phase
  • Added my domain's DNS servers to the intitial network config using NetworkManager
  • Ensured I had the right DNS search suffix (the name of my domain: base.netnerds.net)

Surprisingly, I didn't even have to configure samba after my install was completed. I was prompted to join the domain during the initial OS install and everything went as expected. Here are the settings I used:

samba

I logged in using the domain\username format and this too, worked as expected:

login as: base\chrissy
Using keyboard-interactive authentication.
Password:
Creating directory '/home/BASE/chrissy'.
Creating directory '/home/BASE/chrissy/bin'.
Creating directory '/home/BASE/chrissy/.fonts'.
Creating directory '/home/BASE/chrissy/.mozilla'.
BASE\chrissy@ariel:~>

Next up, setting up NTLM pass-through authentication in Apache!

Update: If you plan to use Kerberos, I recommend you skip straight to using Likewise for all of your authentication needs. I had nothing but headaches from reported bugs with SuSe's built-in Samba and krb5/Kerberos.

Posted by: Chrissy   Filed under: Active Directory, Linux, Networking, Security 4 Comments
8Jan/092

New Network for the New Year

Now that my DL380 is stacked with a total of 10 gigs of ram, it's time to revamp my network. A majority of my servers are still in Silicon Valley (San Jose, specifically) at a fantastic colo company, Silicon Valley Web Hosting so in order to have as little downtime as possible, I'm going to temporarily push that one server to its limit and run a slimmed down virtualized network on it. Since I like my servers to be within driving distance, I'm choosing to migrate the network to Austin, TX (likely at onramp.) Granted Austin is a good 6 hours away, but colocation is much more affordable there than it is in Louisiana and any reason is a good enough reason to visit Austin.

All these new servers will require new names which is cool because the current names of my servers are a random hodgepodge of Cajun references like ROUX (the base for gumbo), BOUDIN (a delicious Cajun sausage) and BOUDREAUX (a famous Cajun last name). I'd like a little more order so I decided to get my theme together beforehand. That way, I don't have to invest time into thinking about names when I create new servers. As I was sitting in the parking lot at Acadian Food Mart in Duson, LA, I decided on the following theme: the names of small cities, towns and villages in Acadiana that are short and double as common first names or nicknames (omg I'm a nerd.) As I was documenting the list of potentials in an email to my business partner and best friend, Brandon, I figured why the hell not document them in Google Maps :D And so I did...


View Larger Map

So the list currently consists of Cade, Leroy, Mack, Katy, Effie, Ellis, Esther, Perry, Cecilia, Elba, Lucy, Henry, Ariel, Vick, Chloe, Lucas, Oliver, Scott, Milton, Jacoby, Brooks, Oscar, Louisa and Coon.

"Coon?" you may be asking yourself. Yes, I know two Coons, one Coonie and one T-Coon. All of whom got their nickname from the controversial epithet "coonass." So far, a few of the roles are: VMware Server, FSMO DC, Backup DC, SQL Server 2008, Backup SQL Server (Mirroring), IIS Web Server, Windows Dev Server, LAMP Server, and uhhh I'll come up with a few more once I get my other servers from SVWH. Did you know that Windows Server 2008 Enterprise edition allows 4 VM installs per physical license? Fortunately, I was able to obtain one of those bad boys at a conference last year and now I have pretty much more than enough Windows 2008 instances. Totally can't wait to try Core w/Powershell.

Posted by: Chrissy   Filed under: Networking 2 Comments
19Jan/086

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

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 adjusting /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.

Posted by: Chrissy   Filed under: Active Directory, Linux, Networking 6 Comments
4Apr/0711

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

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.

Update: A colleague of mine mentioned spyware interfering with proper DNS functionality resulting in intermittent resolution problems. So that's something you may want to check with a netstat -bn which shows you what programs are using which ports. DNS uses UDP port 53.

Posted by: Chrissy   Filed under: Active Directory, Networking, Windows 11 Comments
21Mar/077

Testing Ping Times from an Outside Source

My blogless friend Zach shared this great tip with me: if you would like to test ping times to a machine from an outside source, telnet to route-server.ip.att.net. There, you will be presented with a command line which allows you to ping from the AT&T servers.

############## route-server.ip.att.net ###############
######### AT&T IP Services Route Monitor ###########
The information available through route-server.ip.att.net is offered
by AT&T's Internet engineering organization to the Internet community.
This router has the global routing table view from each of the above
routers, providing a glimpse to the Internet routing table from the
AT&T network's perspective.

This router maintains eBGP peerings with customer-facing routers
throughout the AT&T IP Services Backbone:
12.123.21.243 Atlanta, GA 12.123.133.124 Austin, TX
12.123.41.250 Cambridge, MA 12.123.5.240 Chicago,IL
12.123.17.244 Dallas, TX 12.123.139.124 Detroit, MI
12.123.37.250 Denver, CO 12.123.134.124 Houston, TX
12.123.29.249 Los Angeles, CA 12.123.1.236 New York, NY
12.123.33.249 Orlando,FL 12.123.137.124 Philadelphia, PA
12.123.142.124 Phoenix, AZ 12.123.145.124 San Diego, CA
12.123.13.241 San Francisco, CA 12.123.25.245 St. Louis, MO
12.123.45.252 Seattle, WA 12.123.9.241 Washington, DC

*** Please Note:
Ping and traceroute delay figures measured with this box are unreliable,
due to the high CPU load this box experiences when complicated "show" commands
are being executed.

For questions about this route-server, send email to: jayb@att.com

#################### route-server.ip.att.net ####################

route-server>ping netnerds.net
Translating "netnerds.net"...domain server (12.127.17.83) [OK]

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 69.90.210.117, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 64/66/68 ms

In testing this, I also learned that telnet has been removed from Vista. Now really, Microsoft! Do your helpdesk people really never use telnet to troubleshoot network issues? I used it just yesterday to see if a Citrix server's port was open. What a load of poo. At least I learned another cool trick when researching the removal. Shamit Patel's blog suggested running start /w pkgmgr /iu:"TelnetClient" to install the client from the command line. Worked like a charm.. now to explore other options available with start /w pkgmgr.

Posted by: Chrissy   Filed under: Networking 7 Comments
30Jan/072

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

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

Posted by: Chrissy   Filed under: Networking, SQL Server, VBScript 2 Comments
29Jan/0725

MaxMind GeoIP: Import MaxMind City CSVs into SQL Server 2005

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.

Posted by: Chrissy   Filed under: Networking, SQL Server 25 Comments
25Jan/070

T-SQL UDF: Convert Traditional IP into Numeric IP

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

Posted by: Chrissy   Filed under: Networking, SQL Server No Comments
9Jan/0718

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

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!

Posted by: Chrissy   Filed under: Active Directory, Networking, VBScript 18 Comments