2012-10-29

Encoding sambaNTPassword With Python

Samba's sambaNTPassword attribute, which mimics the corresponding NT / Active Directory attribute, has a value that must be a hex encoded MD4 hash of the user's password with a UTF-16 encoding.  Fortunately generating such a string is a Python one-liner.

import hashlib

password = 'fred123'
nt_password = hashlib.new( 'md4', password.encode('utf-16le')).digest().encode('hex').upper( )

Note that Samba wants all the alpha characters in the string as upper-case.The result will always be 32 characters long.

2012-10-26

Setting a course for UTC

Timezones and daylight savings times are confusing; it is much more complicated that offset-from-UTC.  There are times that occur more that once a year [yep, it hurts] as well as times that are between two valid times but never happen.  It probably requires a Tardis to understand why anyone would want it to work this way.  But, sadly, it does work this way. 
If you stick to the rules, you can safely manage times... so long as those times are all localized.   Naive times, times that are not localized, are the enemy.
Unfortunately there is a lot of code out there, even in important and widely used modules, that uses nieve datetimes.  If you try to use a virtuously localized datetime object with those modules you will likely encounter the dreaded "Cannot compare naive and localized values".
One hack is to make sure the time is localized to the system's timezone, then make it naive, call the module's function, and then re-localize the result (again). Tedious and very prone to error.  The one real problem with this hack is that on most systems the Python process has not @*^$&*@* clue what time zone it is in.  Don't believe me? Try it:
>>> import time
>>> time.tzname
('EST', 'EDT')
Eh, that's a tuple.  And while "EST" is a time zone "EDT" is not a timezone.  Yes, I can determine that I am in daylight savings time locally using time.daylight; but I can't localize a datetime to a daylight timezone because daylight is an attribute of a timezone, not a timezone itself.  That is true regardless of what time.tzname says.  And the "EST" doesn't have daylight savings time, "US/Eastern" does.  "EST" is "US/Eastern" when not it daylight savings time. Gnarly.
But I want to use datetime obejcts reliably and safely with modules that require naive datetime objects....  The answer is to make the timezone known!  I cannot reliably get it from the system but I can make it what I want, and what I want is UTC!  Then my naive datetime objects do not have to be concerned with daylight savings time.  I can just localize them to UTC and subsequently convert them to whatever timezone the user needs to see.  This is accomplished using a combination of the os and time modules.  Early on in my Python application I move myself to UTC.  Here is an example that demonstrates the ugliness of naive times in an unknown timezone, and the beauty of the process being in UTC.
from datetime import datetime
import pytz, time, os

print( 'NOW: {0}'.format( datetime.now( ) ) )
print( 'UTCNOW: {0}'.format(datetime.utcnow( ) ) )
# What timezone is local?  Problem is, most of the time we just do not know.
print( 'LOCALIZEDNOW: {0}'.format( pytz.timezone( 'UTC' ).localize( datetime.now( ) ) ) )
print( 'LOCALIZEDUTC: {0}'.format( pytz.timezone( 'UTC' ).localize( datetime.utcnow( ) ) ) )

#Change to UTC
os.environ[ 'TZ' ] = 'UTC'
time.tzset( )

print( 'NOW: {0}'.format( datetime.now( ) ) )
print( 'UTCNOW: {0}'.format( datetime.utcnow( ) ) )
print( 'LOCALIZEDNOW: {0}'.format( pytz.timezone( 'UTC' ).localize( datetime.now( ) ) ) )
print( 'LOCALIZEDUTC: {0}'.format( pytz.timezone( 'UTC' ).localize( datetime.utcnow( ) ) ) )
And the output:
NOW: 2012-10-26 07:03:31.285486
UTCNOW: 2012-10-26 11:03:31.285570
LOCALIZEDNOW: 2012-10-26 07:03:31.285632+00:00
LOCALIZEDUTC: 2012-10-26 11:03:31.285705+00:00
NOW: 2012-10-26 11:03:31.285787
UTCNOW: 2012-10-26 11:03:31.285812
LOCALIZEDNOW: 2012-10-26 11:03:31.285848+00:00
LOCALIZEDUTC: 2012-10-26 11:03:31.285875+00:00

Now the danger of somehow getting a naive datetime into the mix is completely avoided - I can always safely localize a naive time to UTC.

2012-10-09

Private Networks and Bind 9.9.0

As of BIND 9.9.0 bind is now compliant with RFC6303RFC6303 addresses the issue that everywhere on the Internet private networks are leaking [People - you need egress firewalls..., egress firewalls, not just ingress].  Name servers receive many queries for addresses that are 'private' [see RFC1918]. 

In compliance to RFC6303 bind 9.9.0 will now create default empty zones for the RFC1918 networks - all responses for queries to these domains will be an authoritative NXDOMAIN.  The up-shot is that if you operate an RFC1918 private network, and you update bind, your DNS will stop working as the default empty zones will overlap your configured zones.  The creation of the empty zones is logged when bind starts, you can see them get defined, but it could still be mystifying if you aren't aware of this change. 

If this change impacts your network the configuration directives you are interested in are: empty-zones-enable and disable-empty-zone. The first disables all RFC6303 empty zones - which is the sledge hammer approach.  The second allows the administration to disable specific empty zones.  The second option is preferred, just restore the private networks that you need, but the first will restore your DNS in the short-term. ISC has a good article about toggling off the RFC6303 empty zones for those who operate private networks.

As always: NAT is evil.

2012-10-04

Simple NAT With Cisco IOS

Performing NAT with any variety of a LINUX box is possibly one of the most redundantly documented applications on the Web.  Attempting to do the same with a Cisco IOS router is not documented in so straight-forward a way.
This little snippet shows the configuration for an IOS router where vLAN 13 is a public network and vLAN 12 is a private network.  The router has a public IP address of A.B.C.D [netmask: E.F.G.H] and the gateway address is A.B.C.I.  The private network is a 10.0.0.0/8 with multiple /24 segments which all route to this NAT gateway.
interface FastEthernet0/0.12
 encapsulation dot1Q 12
 ip address 10.66.x.y 255.255.255.0
 ip nat inside
!        
interface FastEthernet0/0.13
 encapsulation dot1Q 13
 ip address A.B.C.D E.F.G.H
 ip nat outside
!        
ip nat inside source list 1 interface FastEthernet0/0.13 overload
ip classless
ip route 0.0.0.0 0.0.0.0 A.B.C.I
access-list 1 permit 10.0.0.0 0.255.255.255
The access-list 1 matches all 10.0.0.0/8 traffic and is used by the ip nat policy which causes the NATing of all matching traffic with the source IP address of the vLAN 13 interface.  The template for the ip nat inside source command is:
ip nat inside source {list {access-list-number | access-list-name} | route-map name} {interface type number | pool name} [mapping-id map-name | vrf name] [overload]
The "overload" option is what enables the routers use of a single address to NAT many local addresses; this corresponds to the default behavior of most iptables configuration tools (does iptables have a "default" behavior?)

One nice feature of using a Cisco for NAT, rather than a host (besides the simplicity of no moving parts) is the very concise reporting provided by "show ip nat translations" and "show ip nat statistics" commands.
Router#show ip nat statistics 
Total active translations: 208 (0 static, 208 dynamic; 208 extended)
Outside interfaces:
  FastEthernet0/0.13
Inside interfaces:
  FastEthernet0/0.12
Hits: 4890142  Misses: 52844
Expired translations: 52640
Dynamic mappings:
-- Inside Source
[Id: 3] access-list 1 interface FastEthernet0/0.13 refcount 208

Similar to "iptables -t nat -L -v" in LINUX.
Additional, and much more technical, documentation for this feature can be found here.

2012-10-03

"D" is for Debugging

My "D" is for Debugging presentation from BarcampGR 2012 is now available.
"D" is for Debugging
In this presentation I covered debugging, not in the developer sense, but in the system administrator sense.  LINUX, and most UNIX and UNIX-like platforms, offer a wide variety of very underutilized tools to discover the root cause of application issues or performance constraints.  With these tools you can not only look under the hood of your system but through the engine block to the moving parts.