Saturday, 8 October 2011

Anatomy of a Netgear WNCE2001 Wireless Transceiver

Recently I bought a wireless transceiver from Netgear. It’s quite tidy at 8cm x 6cm x 1.5cm. I needed it to connnect a bunch of ethernet only devices on a switch to a WPA2 wireless network.


It comes with two connectors: a standard RJ-45 Ethernet port and a power jack which can connect to USB or a standard power socket.

In order to configure this device (with SSID and PSK), the power is connected to the USB on your PC and the ethernet is connected to your ethernet port. After the power and LAN lights go solid, start up your browser and you will automatically be taken to a page to configure the WLAN. Once configured, it operates as a bridge between ethernet and wireless segments.

The level of sophisticaton required to perform the configuration means that this little box must at least have an embedded DHCP server, web server and DNS server on it. Even then it still has to subvert my request for a home page out on the internet and give me back a configuration wizard page.

So I started up Wireshark and watched what happened.
This first section shows the startup through settling down in readiness for configuration:

No.     Time                       Source                Destination           Protocol Info
      1 2011-10-06 16:53:59.741855 CompalIn_fb:67:4c     Nearest               EAPOL    Start
        *** The PC is a potential supplicant requesting authentication in an 802.1X port access control environment (ignored hereafter)

      2 2011-10-06 16:54:02.519609 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0x3df3ee15
        ***DHCP requests repeated (and omitted from here) a few times during INIT-REBOOT state

     10 2011-10-06 16:54:25.718628 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0x2ca33bbe
        ***Here is the first DHCP request from the PC (requesting verification of its last used address) that receives a response

        User Datagram Protocol, Src Port: 68 (68), Dst Port: 67 (67)
        Bootstrap Protocol
            Message type: Boot Request (1)
            Transaction ID: 0x2ca33bbe
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Request
            Option: (t=61,l=7) Client identifier
            Option: (t=50,l=4) Requested IP Address = 192.168.1.73
            Option: (t=12,l=6) Host Name = "PCNAME"
            Option: (t=81,l=31) Client Fully Qualified Domain Name
            Option: (t=60,l=8) Vendor class identifier = "MSFT 5.0"
            Option: (t=55,l=11) Parameter Request List
            Option: (t=43,l=3) Vendor-Specific Information

     12 2011-10-06 16:54:25.757167 192.168.1.251         255.255.255.255       DHCP     DHCP NAK      - Transaction ID 0x2ca33bbe
        *** The Netgear DHCP server tells the PC not to use the address in its last DHCP request
        *** Interesting choice of address by Netgear - keeping away from first or last in case of overlap with the outside WLAN DHCP server?

        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0x2ca33bbe
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP NAK
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.251

     13 2011-10-06 16:54:26.838914 0.0.0.0               255.255.255.255       DHCP     DHCP Discover - Transaction ID 0x5391d124
        *** The PC starts from scratch and asks for a new allocation

        Bootstrap Protocol
            Message type: Boot Request (1)
            Transaction ID: 0x5391d124
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Discover
            Option: (t=116,l=1) DHCP Auto-Configuration = AutoConfigure
            Option: (t=61,l=7) Client identifier
            Option: (t=12,l=6) Host Name = "PCNAME"
            Option: (t=60,l=8) Vendor class identifier = "MSFT 5.0"
            Option: (t=55,l=11) Parameter Request List
            Option: (t=43,l=2) Vendor-Specific Information

     14 2011-10-06 16:54:26.862836 Netgear_77:cf:fe      Broadcast             ARP      Who has 192.168.1.100?  Tell 192.168.1.251
        *** Netgear checks that no one is using the address it wants to use for itself

     15 2011-10-06 16:54:28.929641 192.168.1.251         192.168.1.100         DHCP     DHCP Offer    - Transaction ID 0x5391d124
        *** Netgear gives the PC a new address, and tells it to use the Netgear address for gateway and DNS queries

        User Datagram Protocol, Src Port: 67 (67), Dst Port: 68 (68)
        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0x5391d124
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 192.168.1.100 (192.168.1.100)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Offer
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.251
            Option: (t=51,l=4) IP Address Lease Time = 1 minute
            Option: (t=1,l=4) Subnet Mask = 255.255.255.0
            Option: (t=3,l=4) Router = 192.168.1.251
            Option: (t=6,l=4) Domain Name Server = 192.168.1.251

     16 2011-10-06 16:54:28.930805 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0x5391d124
        *** PC selects its best (only) offer and asks for confirmation

        Bootstrap Protocol
            Message type: Boot Request (1)
            Transaction ID: 0x5391d124
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Request
            Option: (t=61,l=7) Client identifier
            Option: (t=50,l=4) Requested IP Address = 192.168.1.100
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.251
            Option: (t=12,l=6) Host Name = "PCNAME"
            Option: (t=81,l=31) Client Fully Qualified Domain Name
            Option: (t=60,l=8) Vendor class identifier = "MSFT 5.0"
            Option: (t=55,l=11) Parameter Request List
            Option: (t=43,l=3) Vendor-Specific Information

     17 2011-10-06 16:54:28.973606 192.168.1.251         192.168.1.100         DHCP     DHCP ACK      - Transaction ID 0x5391d124
        *** And Netgear confirms. Note that the lease time is only 1 minute

        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0x5391d124
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 192.168.1.100 (192.168.1.100)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP ACK
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.251
            Option: (t=51,l=4) IP Address Lease Time = 1 minute
            Option: (t=1,l=4) Subnet Mask = 255.255.255.0
            Option: (t=3,l=4) Router = 192.168.1.251
            Option: (t=6,l=4) Domain Name Server = 192.168.1.251


     18 2011-10-06 16:54:28.999218 CompalIn_fb:67:4c     Broadcast             ARP      Gratuitous ARP for 192.168.1.100 (Request)
        ** PC sends out a few of these to make sure other devices update their arp tables

     22 2011-10-06 16:54:31.933507 CompalIn_fb:67:4c     Broadcast             ARP      Who has 192.168.1.251?  Tell 192.168.1.100
     23 2011-10-06 16:54:31.933929 Netgear_77:cf:fe      CompalIn_fb:67:4c     ARP      192.168.1.251 is at c4:3d:c7:77:cf:fe
        *** Then updates its own

     *** This is a work PC from an AD and Novell environment. Interesting that Netgear choses to answer these queries
     *** The strategy seems to be to resolve all names to itself
     28 2011-10-06 16:54:32.002898 192.168.1.100         192.168.1.251         DNS      Standard query SRV _ldap._tcp.WORKCampus._sites.dc._msdcs.subdom.workdomain.co.uk
     29 2011-10-06 16:54:32.003300 192.168.1.251         192.168.1.100         DNS      Standard query response SRV
     30 2011-10-06 16:54:32.005632 192.168.1.100         192.168.1.251         DNS      Standard query SOA PCNAME.subdom.workdomain.co.uk
     31 2011-10-06 16:54:32.006002 192.168.1.251         192.168.1.100         DNS      Standard query response SOA[Malformed Packet]
     33 2011-10-06 16:54:32.046312 192.168.1.100         192.168.1.251         DNS      Standard query A time1.workdomain.co.uk
     34 2011-10-06 16:54:32.046677 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251

     35 2011-10-06 16:54:32.054459 192.168.1.100         192.168.1.251         NTP      NTP symmetric active
     36 2011-10-06 16:54:32.055120 192.168.1.251         192.168.1.100         ICMP     Destination unreachable (Port unreachable)
        *** Of course, having inadvertently told the PC that it is a time server, it can't actually handle the ntp request

     *** We get a similar story with SLP:
     37 2011-10-06 16:54:32.237637 192.168.1.100         192.168.1.251         DNS      Standard query A slp1.workdomain.co.uk
     38 2011-10-06 16:54:32.237933 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
     39 2011-10-06 16:54:32.238284 192.168.1.100         192.168.1.251         SRVLOC   Service Request, V2 XID - 3755
     40 2011-10-06 16:54:32.238387 192.168.1.100         192.168.1.251         DNS      Standard query A slp2.workdomain.co.uk
     41 2011-10-06 16:54:32.238623 192.168.1.251         192.168.1.100         ICMP     Destination unreachable (Port unreachable)
     42 2011-10-06 16:54:32.238640 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
     43 2011-10-06 16:54:32.238909 192.168.1.100         192.168.1.251         SRVLOC   Service Request, V1 Transaction ID - 3756
     44 2011-10-06 16:54:32.239248 192.168.1.251         192.168.1.100         ICMP     Destination unreachable (Port unreachable)

     *** Must be time to refresh the arp cache:
     75 2011-10-06 16:54:37.053065 Netgear_77:cf:fe      CompalIn_fb:67:4c     ARP      Who has 192.168.1.100?  Tell 192.168.1.251
     76 2011-10-06 16:54:37.053085 CompalIn_fb:67:4c     Netgear_77:cf:fe      ARP      192.168.1.100 is at 00:1b:38:fb:67:4c
     89 2011-10-06 16:54:40.749850 192.168.1.100         192.168.1.251         ICMP     Echo (ping) request  (id=0x0300, seq(be/le)=16896/66, ttl=1)
     90 2011-10-06 16:54:40.750236 192.168.1.251         192.168.1.100         ICMP     Echo (ping) reply    (id=0x0300, seq(be/le)=16896/66, ttl=64)

     *** Now the Netgear appears to be taking on Netbios master browser functions for the segment - the first exchange of a few is shown only
     92 2011-10-06 16:54:41.009843 192.168.1.100         192.168.1.255         NBNS     Registration NB PCNAME<00>
        NetBIOS Name Service
            Transaction ID: 0x8906
            Flags: 0x2910 (Registration)
                0... .... .... .... = Response: Message is a query
                .010 1... .... .... = Opcode: Registration (5)
                .... ..0. .... .... = Truncated: Message is not truncated
                .... ...1 .... .... = Recursion desired: Do query recursively
                .... .... ...1 .... = Broadcast: Broadcast packet
            Questions: 1
            Answer RRs: 0
            Authority RRs: 0
            Additional RRs: 1
            Queries
                PCNAME<00>: type NB, class IN
                    Name: PCNAME<00> (Workstation/Redirector)
                    Type: NB
                    Class: IN
            Additional records
                PCNAME<00>: type NB, class IN
                    Name: PCNAME<00> (Workstation/Redirector)
                    Type: NB
                    Class: IN
                    Time to live: 3 days, 11 hours, 20 minutes
                    Data length: 6
                    Flags: 0x6000 (H-node, unique)
                        0... .... .... .... = Unique name
                        .11. .... .... .... = H-node
                    Addr: 192.168.1.100

     93 2011-10-06 16:54:41.011045 192.168.1.251         192.168.1.100         NBNS     Name query response NB 192.168.1.251
        NetBIOS Name Service
            Transaction ID: 0x8906
            Flags: 0x8400 (Name query response, No error)
                1... .... .... .... = Response: Message is a response
                .000 0... .... .... = Opcode: Name query (0)
                .... .1.. .... .... = Authoritative: Server is an authority for domain
                .... ..0. .... .... = Truncated: Message is not truncated
                .... ...0 .... .... = Recursion desired: Don't do query recursively
                .... .... 0... .... = Recursion available: Server can't do recursive queries
                .... .... ...0 .... = Broadcast: Not a broadcast packet
                .... .... .... 0000 = Reply code: No error (0)
            Questions: 0
            Answer RRs: 1
            Authority RRs: 0
            Additional RRs: 1
            Answers
                PCNAME<00>: type NB, class IN
                    Name: PCNAME<00> (Workstation/Redirector)
                    Type: NB
                    Class: IN
                    Time to live: 3117 days, 12 hours, 16 minutes
                    Data length: 1536
                    Flags: 0x4000 (M-node, unique)
                        0... .... .... .... = Unique name
                        .10. .... .... .... = M-node
                    Addr: 192.168.1.251

    *** Netgear's strategy of resolving all names to itself means it has to fend off Novell traffic as well:
    102 2011-10-06 16:54:43.389929 192.168.1.100         192.168.1.251         DNS      Standard query A NOVELL-NDS-TREE.subdom.workdomain.co.uk
    103 2011-10-06 16:54:43.390306 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
    104 2011-10-06 16:54:43.390479 192.168.1.100         192.168.1.251         TCP      3438 > 524 [SYN] Seq=0 Win=65535 Len=0 MSS=1260 SACK_PERM=1
    105 2011-10-06 16:54:43.390809 192.168.1.251         192.168.1.100         TCP      524 > 3438 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0


The middle section starts when we launch our browser through to the start of the wizard

    *** Now we start up firefox - interesting to note that firefox appears to look up the home page address before it checks for proxy settings
    164 2011-10-06 16:55:00.309853 192.168.1.100         192.168.1.251         DNS      Standard query A en-gb.start3.mozilla.com
    165 2011-10-06 16:55:00.310404 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
        *** Predictably, Netgear resolves the address to itself

    167 2011-10-06 16:55:00.669057 192.168.1.100         192.168.1.251         DNS      Standard query A wpad.subdom.workdomain.co.uk
    168 2011-10-06 16:55:00.669391 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
        *** Standard behaviour when automatically detect proxy is set - go looking for WPAD

    171 2011-10-06 16:55:00.680058 192.168.1.100         192.168.1.251         TCP      3444 > 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1260 SACK_PERM=1
    172 2011-10-06 16:55:00.680401 192.168.1.251         192.168.1.100         TCP      80 > 3444 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1
    173 2011-10-06 16:55:00.680419 192.168.1.100         192.168.1.251         TCP      3444 > 80 [ACK] Seq=1 Ack=1 Win=65535 Len=0
        *** TCP handshake with the Netgear web server

    174 2011-10-06 16:55:00.680489 192.168.1.100         192.168.1.251         HTTP     GET /wpad.dat HTTP/1.1 
        *** Firefox asks for the javascript proxy script

    176 2011-10-06 16:55:00.689129 192.168.1.251         192.168.1.100         HTTP     HTTP/1.1 200 OK  (text/html)
        *** And Netgear tries to redirect it, however this doesn't include a "function FindProxyForURL(url, host)" so it will be ignored

        Hypertext Transfer Protocol
        Line-based text data: text/html
            <html>\r\n
            \t<head>\r\n
            \r\n
            \t\t<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\n
            \t\t<meta http-equiv="pragma" content="no-cache"> \n
            \t\t<meta http-equiv="cache-control" content="no-cache, must-revalidate"> \n
            \t\t<meta http-equiv="expires" content="0">\t\t<script language="javascript" type="text/javascript">\r\n
            \t\t\tlocation.replace("http://www.mywifiext.net/");\r\n
            \t\t</script>\r\n
            \t</head>\r\n
            \t<body> \r\n
            \t</body>\r\n
            </html>\r\n
            \r\n

    *** Sure enough, Firefox ploughs on to open its original site directly
    177 2011-10-06 16:55:00.761313 192.168.1.100         192.168.1.251         TCP      3445 > 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1260 SACK_PERM=1
    178 2011-10-06 16:55:00.761650 192.168.1.251         192.168.1.100         TCP      80 > 3445 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1
    179 2011-10-06 16:55:00.761663 192.168.1.100         192.168.1.251         TCP      3445 > 80 [ACK] Seq=1 Ack=1 Win=65535 Len=0
    180 2011-10-06 16:55:00.761738 192.168.1.100         192.168.1.251         HTTP     GET /firefox?client=firefox-a&rls=org.mozilla:en-GB:official HTTP/1.1 
        Hypertext Transfer Protocol
            GET /firefox?client=firefox-a&rls=org.mozilla:en-GB:official HTTP/1.1\r\n
            Host: en-gb.start3.mozilla.com\r\n
            User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.23) Gecko/20110920 Firefox/3.6.23 ( .NET CLR 3.5.30729; .NET4.0E)\r\n
            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
            Accept-Language: en-gb,en;q=0.5\r\n
            Accept-Encoding: gzip,deflate\r\n
            Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n
            Keep-Alive: 115\r\n
            Connection: keep-alive\r\n
            Cookie: WT_FPC=id=194.176.105.39-1877985552.30159488:lv=1313671495942:ss=1313671495942\r\n
            \r\n

    182 2011-10-06 16:55:00.764144 192.168.1.251         192.168.1.100         HTTP     HTTP/1.1 200 OK  (text/html)
        *** Netgear has another attempt at redirecting. Note the headers have revealed that Netgear is using lighttpd web server

        Hypertext Transfer Protocol
            HTTP/1.1 200 OK\r\n
            Expires: Sat, 01 Jan 2000 00:00:12 GMT\r\n
            Cache-Control: max-age=1\r\n
            Content-Type: text/html\r\n
            Accept-Ranges: bytes\r\n
            Content-Length: 419\r\n
            Date: Sat, 01 Jan 2000 00:00:55 GMT\r\n
            Server: lighttpd/1.4.18\r\n
            \r\n
        Line-based text data: text/html
            <html>\r\n
            \t<head>\r\n
            \r\n
            \t\t<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\n
            \t\t<meta http-equiv="pragma" content="no-cache"> \n
            \t\t<meta http-equiv="cache-control" content="no-cache, must-revalidate"> \n
            \t\t<meta http-equiv="expires" content="0">\t\t<script language="javascript" type="text/javascript">\r\n
            \t\t\tlocation.replace("http://www.mywifiext.net/");\r\n
            \t\t</script>\r\n
            \t</head>\r\n
            \t<body> \r\n
            \t</body>\r\n
            </html>\r\n
            \r\n

    183 2011-10-06 16:55:00.839579 192.168.1.100         192.168.1.251         DNS      Standard query A www.mywifiext.net
    184 2011-10-06 16:55:00.839907 192.168.1.251         192.168.1.100         DNS      Standard query response A 192.168.1.251
        *** The redirection appears to work as Firefox now locates the new webpage

    185 2011-10-06 16:55:00.840931 192.168.1.100         192.168.1.251         TCP      3446 > 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1260 SACK_PERM=1
    186 2011-10-06 16:55:00.841281 192.168.1.251         192.168.1.100         TCP      80 > 3446 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1
    187 2011-10-06 16:55:00.841300 192.168.1.100         192.168.1.251         TCP      3446 > 80 [ACK] Seq=1 Ack=1 Win=65535 Len=0
    188 2011-10-06 16:55:00.841371 192.168.1.100         192.168.1.251         HTTP     GET / HTTP/1.1 
        *** And we're off - the first page of our wizard
        *** Yards of omitted stuff after this...


Through the wizard, Netgear lists all of the visible SSIDs, allowing one to be selected and  a key to be entered. The last section shows what happens as the Netgear associates to the WLAN and then turns into a bridge (or does it?)

   *** ...and as the last bit of data is finally posted from the wizard:
   1375 2011-10-06 16:56:20.549963 192.168.1.100         192.168.1.251         HTTP     POST /my_cgi.cgi?0.774414189696751 HTTP/1.1  (application/x-www-form-urlencoded)
   1379 2011-10-06 16:56:20.745822 192.168.1.251         192.168.1.100         HTTP/XML HTTP/1.1 200 OK 

   1381 2011-10-06 16:56:21.033167 0.0.0.0               255.255.255.255       DHCP     DHCP Discover - Transaction ID 0x7f52875c
        *** Netgear behaviour suggests that it is now attempting to become a DHCP client on someone else's segment
        *** However, Netgear now has two segments: WLAN and Ethernet, so it appears to be bridging between both mediums

        Bootstrap Protocol
            Message type: Boot Request (1)
            Transaction ID: 0x7f52875c
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: Netgear_77:cf:fe (c4:3d:c7:77:cf:fe)
            Option: (t=53,l=1) DHCP Message Type = DHCP Discover
            Option: (t=61,l=7) Client identifier
            Option: (t=12,l=8) Host Name = "wnce2001"
            Option: (t=60,l=15) Vendor class identifier = "udhcp 0.9.9-pre"
            Option: (t=55,l=10) Parameter Request List

   *** This is confirmed, because we can now at last see traffic from the WLAN coming through:
   1382 2011-10-06 16:56:21.358369 ThomsonT_1b:1c:14     Broadcast             ARP      Who has 192.168.1.74?  Tell 192.168.1.254
   1383 2011-10-06 16:56:21.972481 ThomsonT_1b:1c:14     Broadcast             ARP      Who has 192.168.1.74?  Tell 192.168.1.254
   1385 2011-10-06 16:56:23.061375 0.0.0.0               255.255.255.255       DHCP     DHCP Discover - Transaction ID 0x7f52875c
   1386 2011-10-06 16:56:23.202151 ThomsonT_1b:1c:14     Broadcast             ARP      Who has 192.168.1.74?  Tell 192.168.1.254
        *** This looks like the WLAN router checking a free address:

        Address Resolution Protocol (request)
            Hardware type: Ethernet (0x0001)
            Protocol type: IP (0x0800)
            Hardware size: 6
            Protocol size: 4
            Opcode: request (0x0001)
            [Is gratuitous: False]
            Sender MAC address: ThomsonT_1b:1c:14 (00:26:44:1b:1c:14)
            Sender IP address: 192.168.1.254 (192.168.1.254)
            Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)
            Target IP address: 192.168.1.74 (192.168.1.74)

   1387 2011-10-06 16:56:23.205098 192.168.1.254         255.255.255.255       DHCP     DHCP Offer    - Transaction ID 0x7f52875c
        *** ... before giving it to Netgear. Note the lease is a decent length now.

        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0x7f52875c
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 192.168.1.74 (192.168.1.74)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 192.168.1.254 (192.168.1.254)
            Client MAC address: Netgear_77:cf:fe (c4:3d:c7:77:cf:fe)
            Option: (t=53,l=1) DHCP Message Type = DHCP Offer
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.254
            Option: (t=51,l=4) IP Address Lease Time = 1 day
            Option: (t=1,l=4) Subnet Mask = 255.255.255.0
            Option: (t=6,l=4) Domain Name Server = 192.168.1.254
            Option: (t=15,l=4) Domain Name = "home"
            Option: (t=3,l=4) Router = 192.168.1.254


   1388 2011-10-06 16:56:23.261309 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0x7f52875c
        *** Netgear asks for confirmation that it can use the address
        Bootstrap Protocol
            Transaction ID: 0x7f52875c
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: Netgear_77:cf:fe (c4:3d:c7:77:cf:fe)
            Option: (t=53,l=1) DHCP Message Type = DHCP Request
            Option: (t=61,l=7) Client identifier
            Option: (t=12,l=8) Host Name = "wnce2001"
            Option: (t=60,l=15) Vendor class identifier = "udhcp 0.9.9-pre"
            Option: (t=50,l=4) Requested IP Address = 192.168.1.74
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.254
            Option: (t=55,l=10) Parameter Request List

   *** slightly different behaviour from the main WLAN router - it is also arping at offer stage
   1389 2011-10-06 16:56:24.123034 ThomsonT_1b:1c:14     Broadcast             ARP      Who has 192.168.1.74?  Tell 192.168.1.254
   1390 2011-10-06 16:56:25.044698 ThomsonT_1b:1c:14     Broadcast             ARP      Who has 192.168.1.74?  Tell 192.168.1.254

   *** ...and we see the Netgear DHCP transaction go onto complete on that IP address
   *** I have a mild concern here about why a wireless bridge with a sophisticated embedded Linux system would require layer 3 membership on my WLAN...
   1391 2011-10-06 16:56:25.309071 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0x7f52875c
   1392 2011-10-06 16:56:26.275711 192.168.1.254         255.255.255.255       DHCP     DHCP Offer    - Transaction ID 0x7f52875c
   1393 2011-10-06 16:56:26.279179 192.168.1.254         255.255.255.255       DHCP     DHCP ACK      - Transaction ID 0x7f52875c
   1394 2011-10-06 16:56:26.282191 192.168.1.254         255.255.255.255       DHCP     DHCP ACK      - Transaction ID 0x7f52875c
   1395 2011-10-06 16:56:27.157069 Netgear_77:cf:fe      Broadcast             ARP      Who has 192.168.1.254?  Tell 192.168.1.74

   *** But what about our PC? it seems somehow to have twigged that something has changed - DHCP requests (although still unicast), EAPOL etc
   *** I didn't notice Netgear dropping the ethernet link, but it that would have been one way to do it
   1396 2011-10-06 16:56:28.252537 192.168.1.100         192.168.1.251         DHCP     DHCP Request  - Transaction ID 0x7e41999d
   1397 2011-10-06 16:56:36.393373 192.168.1.100         192.168.1.251         ICMP     Echo (ping) request  (id=0x0300, seq(be/le)=17152/67, ttl=1)
   1398 2011-10-06 16:56:36.420095 CompalIn_fb:67:4c     Nearest               EAPOL    Start
   1399 2011-10-06 16:56:37.414054 192.168.1.100         192.168.1.251         ICMP     Echo (ping) request  (id=0x0300, seq(be/le)=17408/68, ttl=1)
   1401 2011-10-06 16:56:38.915020 192.168.1.100         192.168.1.251         ICMP     Echo (ping) request  (id=0x0300, seq(be/le)=17664/69, ttl=1)

   *** After about 12 secs, the PC starts broadcasting its request to extend the lease on its existing IP address
   1402 2011-10-06 16:56:40.418751 192.168.1.100         255.255.255.255       DHCP     DHCP Request  - Transaction ID 0xc0964cdc
        Bootstrap Protocol
            Message type: Boot Request (1)
            Transaction ID: 0xc0964cdc
            Client IP address: 192.168.1.100 (192.168.1.100)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 0.0.0.0 (0.0.0.0)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Request
            Option: (t=61,l=7) Client identifier
            Option: (t=12,l=6) Host Name = "PCNAME"
            Option: (t=81,l=31) Client Fully Qualified Domain Name
            Option: (t=60,l=8) Vendor class identifier = "MSFT 5.0"
            Option: (t=55,l=11) Parameter Request List
            Option: (t=43,l=3) Vendor-Specific Information

   1403 2011-10-06 16:56:40.717438 192.168.1.254         255.255.255.255       DHCP     DHCP NAK      - Transaction ID 0xc0964cdc
        *** But, predictably, WLAN router says no!

        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0xc0964cdc
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 0.0.0.0 (0.0.0.0)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 192.168.1.254 (192.168.1.254)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP NAK
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.254
            Option: (t=56,l=26) Message = "REQUEST for invalid lease"

   1409 2011-10-06 16:56:45.836342 0.0.0.0               255.255.255.255       DHCP     DHCP Discover - Transaction ID 0xc9b00679
        *** So we start from scratch again

   1410 2011-10-06 16:56:45.939624 192.168.1.254         255.255.255.255       DHCP     DHCP Offer    - Transaction ID 0xc9b00679
        *** New address for use on WLAN

        Bootstrap Protocol
            Message type: Boot Reply (2)
            Transaction ID: 0xc9b00679
            Client IP address: 0.0.0.0 (0.0.0.0)
            Your (client) IP address: 192.168.1.73 (192.168.1.73)
            Next server IP address: 0.0.0.0 (0.0.0.0)
            Relay agent IP address: 192.168.1.254 (192.168.1.254)
            Client MAC address: CompalIn_fb:67:4c (00:1b:38:fb:67:4c)
            Option: (t=53,l=1) DHCP Message Type = DHCP Offer
            Option: (t=54,l=4) DHCP Server Identifier = 192.168.1.254
            Option: (t=51,l=4) IP Address Lease Time = 1 day
            Option: (t=1,l=4) Subnet Mask = 255.255.255.0
            Option: (t=15,l=4) Domain Name = "home"
            Option: (t=6,l=4) Domain Name Server = 192.168.1.254
            Option: (t=3,l=4) Router = 192.168.1.254

   *** And then the transaction completes as before
   1411 2011-10-06 16:56:45.940058 0.0.0.0               255.255.255.255       DHCP     DHCP Request  - Transaction ID 0xc9b00679
   1412 2011-10-06 16:56:46.246842 192.168.1.254         255.255.255.255       DHCP     DHCP ACK      - Transaction ID 0xc9b00679
   1414 2011-10-06 16:56:46.273772 CompalIn_fb:67:4c     Broadcast             ARP      Gratuitous ARP for 192.168.1.73 (Request)
   1415 2011-10-06 16:56:46.421869 CompalIn_fb:67:4c     Nearest               EAPOL    Start
   1416 2011-10-06 16:56:46.914798 CompalIn_fb:67:4c     Broadcast             ARP      Gratuitous ARP for 192.168.1.73 (Request)
   1420 2011-10-06 16:56:47.471850 CompalIn_fb:67:4c     ThomsonT_1b:1c:14     ARP      192.168.1.73 is at 00:1b:38:fb:67:4c


   *** Lastly, of mild interest only, is the difference in behaviour between the Netgear DNS and the broadband router DNS
   *** This is now back to normal behaviour
   1447 2011-10-06 16:56:49.006741 192.168.1.73          192.168.1.254         DNS      Standard query SRV _ldap._tcp.WORKCampus._sites.dc._msdcs.subdom.workdomain.co.uk
   1449 2011-10-06 16:56:49.046225 192.168.1.254         192.168.1.73          DNS      Standard query response, No such name
   1450 2011-10-06 16:56:49.062867 192.168.1.73          192.168.1.254         DNS      Standard query SRV _ldap._tcp.dc._msdcs.subdom.workdomain.co.uk
   1451 2011-10-06 16:56:49.071474 192.168.1.73          192.168.1.254         DNS      Standard query SOA PCNAME.subdom.workdomain.co.uk
   1452 2011-10-06 16:56:49.094456 192.168.1.254         192.168.1.73          DNS      Standard query response, No such name
   1453 2011-10-06 16:56:49.101329 192.168.1.254         192.168.1.73          DNS      Standard query response, No such name


So quite a slick operation, but one that requires me to be happy having a third-party linux server sitting on my network disguised as a dumb transceiver. As far as I could see (from my broadband router arp table), the server went to sleep once it had done its job of creating a WLAN bridge, but who knows if it could be woken up...

Monday, 19 September 2011

Nagios Plugin 'check_procs' incorrectly finds 0 processes

When checking for running processes on remote Linux systems via NRPE, the Nagios plugin check_procs –C <process commandname> occasionally responds with unexpected results.

Example on a Zenworks 7 server

If we look for the tftpd daemon using ps:
ZEN03:/usr/local/nagios/libexec # ps -ef|grep tftpd
root     4103      1  0 Sep14 ?        00:01:31 /opt/novell/bin/novell-tftpd
root     20047 17950  0 13:06 pts/0    00:00:00 grep tftpd

Then we look for it with check_procs:
ZEN03:/usr/local/nagios/libexec # ./check_procs -C novell-tftpd
PROCS OK: 1 process with command name 'novell-tftpd'

The check_procs plugin correctly reports that one process has been found with this name

However, if we look for the proxy dhcp daemon using ps:
ZEN03:/usr/local/nagios/libexec # ps -ef |grep proxy
root  21171     1  0 Sep18 ?        00:00:00 /opt/novell/bin/novell-proxydhcpd
root  20137 17950  0 13:07 pts/0    00:00:00 grep proxy

And then with check_procs:
ZEN03:/usr/local/nagios/libexec # ./check_procs -C novell-proxydhcpd
PROCS OK: 0 processes with command name 'novell-proxydhcpd'

In this case,  the check_procs plugin has reported that 0 processes have been found, even though we can clearly see that this is not the case.

The trick in these situations is to ask check_procs for more information using the –vv switch:
ZEN03:/usr/local/nagios/libexec # ./check_procs -vv -C novell-proxydhcpd
CMD: /bin/ps axwo 'stat uid pid ppid vsz rss pcpu comm args'
PROCS OK: 0 processes with command name 'novell-proxydhcpd'

Here check_procs has told us what it is passing to ps to find out the information it is reporting back to us.

So let us use that parameter list for our own check:
ZEN03:/usr/local/nagios/libexec # /bin/ps axwo 'stat uid pid ppid vsz rss pcpu comm args'|grep proxy
S       0 21171     1   1412   396  0.0 novell-proxydhc /opt/novell/bin/novell-proxydhcpd
S+      0 20263 17950   1712   672  0.0 grep            grep proxy

And there it is – on this system (SLES9), ps is only reporting back the first 15 characters, so no match is being found.

So here, what we have to do is to ask check_procs to only look for the first 15 characters
ZEN03:/usr/local/nagios/libexec # ./check_procs -C novell-proxydhc
PROCS OK: 1 process with command name 'novell-proxydhc'

We can now correctly check for our proxy dhcp daemon in Nagios.

Monday, 12 September 2011

Nagios check_vmfs Quirk

I came across Duncan Epping's check_vmfs bash script the other day when I was looking at what NRPE could do in our ESX 3.5 environment. It's fairly basic and did what it said it could do: report on vmfs space utilisation.

For interest, here is a copy of the script I wanted to use:

#!/bin/bash
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
MYVOL=$1
WARNTHRESH=$2
CRITTHRESH=$3
RET=$?
if [[ $RET -ne 0 ]]
    then
    echo "query problem - No data received from host"
    exit $STATE_UNKNOWN
fi
vdf -h -P | grep -E '^/vmfs/volumes/' | awk '{ print $2 " " $3 " " $4 " " $5 " " $6 }' | while read output ; do
DISKSIZE=$(echo $output | awk '{ print $1 }' )
DISKUSED=$(echo $output | awk '{ print $2 }' )
DISKAVAILABLE=$(echo $output | awk '{ print $3 }' )
PERCENTINUSE=$(echo $output | awk '{ print $4 }' )
VOLNAME=$(echo $output | awk '{ print $5 }' )
CUTPERC=$(echo $PERCENTINUSE | cut -d'%' -f1 )
if [ "/vmfs/volumes/$MYVOL" = $VOLNAME ] ; then
    if [ $CUTPERC -lt $WARNTHRESH ] ; then
        echo "OK - $PERCENTINUSE used | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
        exit $STATE_OK
    fi
    if [ $CUTPERC -ge $CRITTHRESH ] ; then
        echo "CRITICAL - *$PERCENTINUSE used* | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
        exit $STATE_CRITICAL
    fi
    if [ $CUTPERC -ge $WARNTHRESH ] ; then
        echo "WARNING - *$PERCENTINUSE used* | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
        exit $STATE_WARNING
    fi
fi
#echo "No data returned"
#exit $STATE_UNKNOWN

However, in a SAN environment where every host in an ESX environment has the same LUNs attached for HA, having every host report on space utilisation for the same list of LUNs is a bit over the top, and I'm actually more interested in knowing if a host has lost its path(s) to a LUN.

So I thought I would make a small modification to the script so that it would actually complain if the VMFS (LUN) disappeared. In its original form the script would produce no output to cover this eventuality, and I thought I could see why: the two commented lines just before the end of the while loop needed to be uncommented, changed to report a missing vmfs and moved outside the loop to pick up anything that didn't hit any of the exit statements. It should have taken about 30 seconds.

Well I spent about an hour grappling with a very curious symptom: if any of the conditions inside the loop were met, the script would provide the correct response, but then, instead of exiting, would appear to carry on executing any statements after the loop. This meant that the script would report that it had found a vmfs volume AND report that it couldn't find it. I tried setting variables inside the loop to pick up back in the main section, even exporting them to make them exist outside the script; but I seemed to be stuck with some sort of scoping problem.

It was only when I came across an article by Craig Russell on BASH variable scope inside a While loop, that I realised what the problem was: the while loop was sitting on the end of a pipe and in Bash that meant that the while loop was running in a different process. So the exit statements and any variables set inside the loop have no effect in the outer script.

Craig had a reasonable alternative - pipe out to a temporary file and hang the while loop onto the file instead. I was then able to implement my properly performing script:

#!/bin/sh
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3

MYVOL=$1
WARNTHRESH=$2
CRITTHRESH=$3
RET=$?

if [[ $RET -ne 0 ]]
then
  echo "query problem - No data received from host"
  exit $STATE_UNKNOWN
fi

vdf -h -P | grep -E '^/vmfs/volumes/' | awk '{ print $2 " " $3 " " $4 " " $5 " " $6 }' >/tmp/vmfslist.tmp

while read output
  do
  DISKSIZE=$(echo $output | awk '{ print $1 }' )
  DISKUSED=$(echo $output | awk '{ print $2 }' )
  DISKAVAILABLE=$(echo $output | awk '{ print $3 }' )
  PERCENTINUSE=$(echo $output | awk '{ print $4 }' )
  VOLNAME=$(echo $output | awk '{ print $5 }' )
  CUTPERC=$(echo $PERCENTINUSE | cut -d'%' -f1 )
  if [ "/vmfs/volumes/$MYVOL" = $VOLNAME ]
    then
    if [ $CUTPERC -lt $WARNTHRESH ]
      then
      echo "OK - $PERCENTINUSE used | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
      exit $STATE_OK
    elif [ $CUTPERC -ge $CRITTHRESH ]
      then
      echo "CRITICAL - *$PERCENTINUSE used* | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
      exit $STATE_CRITICAL
    elif [ $CUTPERC -ge $WARNTHRESH ]
      then
      echo "WARNING - *$PERCENTINUSE used* | Volume=$MYVOL Size=$DISKSIZE Used=$DISKUSED Available=$DISKAVAILABLE PercentUsed=$PERCENTINUSE"
      exit $STATE_WARNING
    fi
  fi
done < /tmp/vmfslist.tmp

echo "No data returned. VMFS Unavailable?"
exit $STATE_CRITICAL


The lesson? There's no real substitute for knowing how stuff works... properly.

Tuesday, 30 August 2011

Nagios AD Authentication

Installing a new Nagios/MRTG/OpenNMS server recently under SUSE10, I had a few problems getting AD credentials to work consistently across web and ssh interfaces.

While I'm not going to bore with my full step-by-step server build doc, I have extracted the Kerberos steps, hoping it will make someone else's life a little easier.

So we start at the point where we have built and activated the server, configured networking and installed vmware tools, but we haven't installed Nagios.

Time Synchronisation - this is very important as Kerberos only tolerates 5 minutes clock differences. So as well as installing ntp, I still add clock=pit to the end of my kernel= line in /boot/grub/menu.lst

Install Kerberos client through yast networking services. Ensure the default dns domain matches resolv.conf; ensure that the default realm matches your AD, and is in CAPITALS; supply your nearest DC's FQDN as KDC server.

Edit krb5.conf
vi /etc/krb5.conf
(insert after [libdefaults])
dns_lookup_realm = true
dns_lookup_kdc = true

With just this first change, you should be able to authenticate using your AD credentials 
SRV09 # kinit -V myadusername
Password for myadusername@MYADREALM.INTERNAL:
Authenticated to Kerberos v5
SRV09 #

If you get any errors containing "...not match expectations..." check your krb5.conf for typos

Now we have to enable kerberos in PAM.

Edit pam_unix2.conf and check that the following lines are present:
vi /etc/security/pam_unix2.conf
auth: use_krb5 nullok
account: use_krb5
password: use_krb5 nulllok
session: none

Every participating AD user must have a local account exactly matching their AD username :
useradd –c “My Full Name” –m myadusername

Finish the job by sorting out su and sudo - add the user to the wheel group:
usermod –G wheel myadusername

Enforce use of the wheel group
chown root:wheel /bin/su
chmod o-rx /bin/su
chmod u+s /bin/su

Configure sudo - I just allow access from the wheel group, but you can configure how you like.
visudo
(modify)
#Defaults targetpw
#ALL ALL=(ALL) ALL
%wheel ALL=(ALL) ALL

At this point you should be able to log on via ssh with your AD credentials and use su to root or execute programs with root privilege through sudo if necessary.

Once you have verified this, you can disable root access to sshd:
vi /etc/ssh/sshd_config
(modify)
PermitRootLogin no

Restart SSHD
/etc/init.d/sshd restart

Now we're ready to take on Apache...

Run yast and install the following packages:
apache2
apache-mod_php5

This gets enough Apache in place to install Nagios.
So we run through the Nagios core and plugins installation until we get to
...
make install-webconf
htpasswd2 –c /usr/local/nagios/etc/htpasswd.users nagiosadmin

Now when we restart Apache we should be able to get to the basic Nagios website, to be prompted for the local nagiosadmin credentials.
/etc.init.d/apache2 restart

Ensure all authenticated users have required accesses
vi /usr/local/nagios/etc/cgi.cfg
(modify)
authorized_for_all_services=*
authorized_for_all_hosts=*
authorized_for_all_service_commands=*
authorized_for_system_information=*
authorized_for_configuration_information=*


Now we need to update Apache to use PAM. First run yast and install the following packages:
apache2-devel
pam-devel

Download and expand the pam module source tar file
cd /var/tmp
wget http://pam.sourceforge.net/mod_auth_pam/dist/mod_auth_pam-2.0-1.1.1.tar.gz
tar xzpf mod_auth_pam-2.0-1.1.1.tar.gz
cd mod_auth_pam/

Correction for Apache 2
vi Makefile
(replace) APXS=apxs
(with) APXS=/usr/sbin/apxs2

Compile and install module
make
make install

Tell Apache about the new module:
vi /etc/sysconfig/apache2
(find line beginning with: APACHE_MODULES and add auth_pam and auth_sys_group to the list)

Change system-wide authentication / authorisation to per-directory
vi /etc/apache2/httpd.conf
(under) <Directory />
(replace) AllowOverride None
(with) AllowOverride AuthConfig

Configure PAM parameters for Apache
vi /etc/pam.d/httpd
(remove everything and insert:)
auth          required      /lib/security/pam_env.so
auth          sufficient    /lib/security/pam_krb5.so minimum_uid=1
auth          required      /lib/security/pam_deny.so
account       required      /lib/security/pam_krb5.so

Edit Nagios apache configuration to force PAM authentication
vi /etc/apache2/conf.d/nagios.conf
(replace everything in <Directory…> brackets with):
   SSLRequireSSL       (optional - I'm assuming that you compiled with SSL):
   Options ExecCGI
   AllowOverride None
   Order allow,deny
   Allow from all
   AuthName "My AD Domain”
   AuthPAM_Enabled on
   AuthPAM_FallThrough off
   AuthBasicAuthoritative off
   AuthGROUP_Enabled off
   AuthUserFile /dev/null
   AuthType Basic
   Require valid-user


Restart Apache (check for errors)
/etc/init.d/apache restart

And that's the main enabling configuration done!

So in future, when we want to add an AD user to Nagios, these are the steps we have to carry out:

Create a local username identical to the AD username
useradd –c “User Full Name” –m adusername

Add the username to the wheel group
usermod –G wheel adusername

Add the username to Nagios Contacts
vi /usr/local/nagios/etc/objects/contacts.cfg
define contact{
   contact_name                    adusername
    use                             generic-contact
    alias                           User Full Name
    host_notification_commands      notify-host-by-email
    service_notification_commands   notify-service-by-email
    email                           adusermailname@somedomain.net
    }

Add the username to Nagios Admins Group
define contactgroup{
        contactgroup_name       admins
        alias                   Nagios Administrators
        members                 nagiosadmin,adusername
        }

Create a Nagios account using the username (password is ignored, leave blank)
htpasswd2 –c /usr/local/nagios/etc/htpasswd.users adusername

If the user is only to have readonly rights:
vi /usr/local/nagios/etc/cgi.cfg
(modify)
authorized_for_read_only=adusername,user2,etc

Restart Nagios
/etc/init.d/nagios restart

Sunday, 28 August 2011

Reading the Clipboard from VBScript

I was recently working on some scripting for managing a couple of hundred Cisco devices, to automate bulk ACL changes, backups and suchlike via PuTTY. At one point I came to the conclusion that it would be useful to be able to access the clipboard from a vbscript running under cscript.exe, and went looking for some starter code. I was surprised to find that no such code existed, or that if it existed, it relied on an external program such as clip.exe.

The problem seems to be that clipboard lives in Gui userland, and my scripts live in Text userland. So the solution I would need to come up with would have to go to the Windows environment in order to access the abstraction that is clipboard, and bring it back to my text environment.

My first cut solution uses a pseudo-netsocket approach - spawn another process and establish two-way communication using PIDs, then paste into its windows interface, and have it send what it receives to my stdin.

It works surprisingly well (in my environment) and although ultimately I decided not to use it for my Cisco project, I have added it to my libaries for process management. Here it is with only minimal error checking for clarity.

Option Explicit

'===========================================================================
'Name:    GetClipBoard() function
'Author:  Philip Damian-Grint
'Version: 1.0
'Date:    28th Aug 2011
'
'Description:
'
'  From a vbs script running under cscript.exe, read the contents of the 
'  Clipboard into a string.
'===========================================================================

Function GetClipBoard

    ' First we create a text file to hold our child
    dim objFS : Set objFS = CreateObject("Scripting.FileSystemObject")
    dim strFName : strFName = objFS.GetTempName
    dim objTS : Set objTS = objFS.CreateTextFile( strFName, True )

    ' Our child requests her parent's PID, and then provides a paste buffer, all off-screen
    objTS.WriteLine("dim pid : pid=inputbox(""PID"",,,0,-3000) : " & _
            "dim str : str=inputbox(""STR"",,,0,-3000) : " & _
            "set shell=wscript.createobject(""wscript.shell"") : " & _
            "shell.appactivate pid : wscript.sleep 100 : " & _
            "shell.sendkeys str & ""{ENTER}""")
    objTS.Close

    ' Spawn our child as a running process
    Dim objWshShell : Set objWshShell = WScript.CreateObject("WScript.Shell")
    Dim objChild : Set objChild = objWshShell.exec( "cscript.exe //E:vbscript " & strFName )
    Dim intChildPID : intChildPID = clng(objChild.ProcessID)

    ' Now use our child's PID to find our own
    Dim strObjPath : strObjPath = "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"
    Dim objProcess, intParentPID

    For Each objProcess In getObject( strObjPath ).instancesOf("Win32_Process")
        If intChildPID = (clng(objProcess.processID)) Then
            intParentPID= objProcess.parentProcessID : Exit For
        End If
    Next

    ' Find our child's first input box, and write our PID to it
    Do until objWshShell.AppActivate( intChildPID )
        WScript.Sleep 100
    Loop : objWshShell.SendKeys intParentPID & "{ENTER}"

    ' Find our child's second input box, and paste the clipboard contents
    Do Until objWshShell.AppActivate( intChildPID )
        WScript.Sleep 100
    Loop : objWshShell.SendKeys "^v{ENTER}"

    ' Receive the paste buffer contents from our child
    GetClipBoard  = WScript.StdIn.ReadLine

    ' And clear up after our child
    objFS.DeleteFile strFName, True

End Function

' Demonstrate the function

wscript.echo "We read: " & GetClipBoard() & " from the clipboard"