Archive for the ‘Tutorials’ Category

Cisco 3750 Password Recovery

Monday, June 1st, 2009


This password recovery method also applies to at least the:
Cisco 2950, Cisco 2960, Cico 3550, Cisco 3560 and Cisco 3750 series.
The only difference will be for how long you will hold the mode button,
from my experience just try to hold it longer if it doesn’t work.
(It should be around 15 seconds for the 3750.)

Connect the PC to the console port
Settings:

  • 9600 bits
  • 8 data bits
  • ‘none’ parity
  • 1 stop bit

If the switch is powered on, power it off and press and hold the mode button while you power on the switch again. Hold it for about 15 seconds until the SYS led is solid green, then release it.

The switch should then give you this prompt

switch:

To initialize the flash file system, run the command

switch: flash_init

The switch will now print a bunch of messages about the flash memory, hopefully one of them will be ‘done initializing flash’.
The next command is load_helper to load any helper images required by boot.

You can now list the contents of your flash by running dir flash:
There should be a file named ‘config.text’, you can rename this file

switch: rename flash:config.text flash:oldconfig.backup

To further boot the switch run the boot command, this will start the boot you are used to. When the switch is booted up, you will realize that the configuration is gone.. But you are enabled on the switch now.

To recover the old configuration:

Switch#rename flash:oldconfig.backup flash:config.text

And now to replace the running configuration with the backup

Switch#copy flash:config.text running-config
Destination filename [running-config]?

Press enter, and you will have your old switch configuration back and you are enabled.
Just remember to change your password now! 😀

HOWTO: Gathering All The Information About An IP Address

Thursday, May 21st, 2009

Would you like to know more about that attacker or who the sucker that draws all your bandwidth is? You can!

The information is stored all around the internet, I will use one of the addresses that RIPE resolves to in this example.
I am using a linux system, but here is an online whois tool that you can use.

$ host ripe.net
ripe.net has address 193.0.19.25
ripe.net has IPv6 address 2001:610:240:11::c100:1319

Now, it’s is not always like this because some of the addresses have records in ARIN (North American Region) and other registries around the world, but I will focus a bit on the RIPE database right now.

As we can see, ripe.net resolves to 193.0.19.25, to figure out a bit more you can do a whois for that IP address.

$ whois 193.0.19.25
% This is the RIPE Whois query server #3.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See http://www.ripe.net/db/support/db-terms-conditions.pdf

% Note: This output has been filtered.
% To receive output for a database update, use the “-B” flag.

% Information related to ‘193.0.18.0 – 193.0.21.255’

inetnum: 193.0.18.0 – 193.0.21.255
netname: RIPE-NCC
descr: RIPE Network Coordination Centre
descr: Amsterdam, Netherlands
remarks: Used for RIPE NCC infrastructure.
country: NL
admin-c: AMR68-RIPE
admin-c: BRD-RIPE
tech-c: OPS4-RIPE
status: ASSIGNED PI
mnt-by: RIPE-NCC-MNT
mnt-lower: RIPE-NCC-MNT
source: RIPE # Filtered

role: RIPE NCC Operations
address: Singel 258
address: 1016 AB Amsterdam
address: The Netherlands
phone: +31 20 535 4444
fax-no: +31 20 535 4445
e-mail: X@ripe.net
admin-c: AMR68-RIPE
admin-c: BRD-RIPE
tech-c: GL7321-RIPE
tech-c: JA47
tech-c: MENN1-RIPE
tech-c: EMIL-RIPE
tech-c: SSIE-RIPE
tech-c: RCO-RIPE
tech-c: APZ-RIPE
tech-c: CNAG-RIPE
tech-c: SMCA-RIPE
tech-c: BOH-RIPE
nic-hdl: OPS4-RIPE
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

… output omitted …

% Information related to ‘193.0.18.0/23AS3333’

route: 193.0.18.0/23
descr: RIPE-NCC
origin: AS3333
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

You can see from the whois output that this address is part of the address range 193.0.18.0 – 193.0.21.255 which has been delegated to RIPE NCC. It lives in the prefix 193.0.18.0/23 which is supposedly announced by AS3333.

Check the Real World BGP
We can check if this is correct by using a looking glass, I found that AS6453 got an online looking glass.
Choose BGP and enter the IP address 193.0.19.25.
Look for: BGP routing table entry for 193.0.0.0/21. Right, it is announced as a /21 on the internet.

We can go further and perform an inverse query to check for other prefixes that AS3333 have registered to see if it’s part of a larger range.

This time I have to ask whois.ripe.net directly because the whois tool on linux automatically chooses the correct whois server for an object, and it does not understand which whois server it should send inverse queries to.

$ whois -h whois.ripe.net — -i origin AS3333
% This is the RIPE Whois query server #3.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See http://www.ripe.net/db/support/db-terms-conditions.pdf

% Note: This output has been filtered.
% To receive output for a database update, use the “-B” flag.

% Information related to ‘193.0.0.0/21AS3333’

route: 193.0.0.0/21
descr: RIPE-NCC
origin: AS3333
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

% Information related to ‘193.0.12.0/23AS3333’

route: 193.0.12.0/23
descr: RIPE-NCC
descr: Specific range for nameserver operations.
origin: AS3333
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

% Information related to ‘193.0.18.0/23AS3333’

route: 193.0.18.0/23
descr: RIPE-NCC
origin: AS3333
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

% Information related to ‘193.0.20.0/23AS3333’

route: 193.0.20.0/23
descr: RIPE-NCC
origin: AS3333
mnt-by: RIPE-NCC-MNT
source: RIPE # Filtered

There we go 193.0.0.0/21 is registered there as well, now this is actually part of a (seems like) special /18 which parts of is handed out to network operators. According to remarks, RIPE itself has taken 193.0.0.0/19 for their own network. (And this is just a little of what information I gathered in three minutes.)

A whois of the AS Number:

$ whois AS3333
[… output omitted ….]
% Information related to ‘AS3333’

aut-num: AS3333
as-name: RIPE-NCC-AS
descr: RIPE Network Coordination Centre
[… output omitted …]

Usually you can find references to an org, to check a prefix just use the command whois PREFIX | grep ^org, or use egrep to also get type of address space; you will then often get a result like this:

$ whois 193.0.0.0/18 | egrep \(^org\|^status\)
org: ORG-NCC1-RIPE
status: ALLOCATED UNSPECIFIED
organisation: ORG-NCC1-RIPE
org-name: RIPE NCC
org-type: RIR

The org-name is the name of the organisation, the type can be for example:

  1. RIR – Regional Internet Registry (king of the hill [or continent])
  2. LIR – Local Internet Registry (basically an ISP)
  3. OTHER – Other type, for example users of PI address space

The status is the type of address space, it can be for example:

  1. ALLOCATED UNSPECIFIED – This is often legacy address space which was not handed out under current conditions.
  2. ALLOCATED PA – Provider Aggregatable, which is a larger address space handed out to LIRs for sub delegations.
  3. ALLOCATED PI – Provider Independent, handed out to smaller organisations (registered as OTHER) which are NOT members of the RIPE NCC (LIRs), this kind of address space makes it possible for a company to multihome and change providers without changing IP addresses. (Rather than getting assignments from a larger PA address space)

I guess you figured out that you can also whois the org name, ‘ORG-NCC1-RIPE’.

Let me know if I also should write a tutorial on how to update and perform changes to the RIPE whois database!

Cisco IP Phone Configuration with Asterisk

Wednesday, May 20th, 2009

Getting the Cisco IP Phone 7970 G to work together with the software PBX Asterisk was something I had my hands on a couple of years back. Here’s how you can get them talking together.

You need a couple of things to get this working:

  1. A functioning DHCP server
  2. A functioning TFTP server
  3. SIP Firmware from Cisco This is just a gzipped and tar’ed file.
  4. A functioning asterisk server
  5. A Cisco IP Phone

According to a recent installation, the TFTP server must contain the following files

apps70.1-1-2-26.sbn
cnu70.3-1-2-26.sbn
cvm70sip.8-0-2-25.sbn
dsp70.1-1-2-26.sbn
jar70sip.8-0-2-25.sbn
SIP70.8-0-3S.loads
term70.default.loads
term71.default.loads
SEP<MACADDRESS>.cnf.xml

The file you should pay the most attention to is the SEP<MACADDRESS>.cnf.XML file, this is the configuration file. The configuration file is in XML format. You can find a sample configuration here that should work.

<device xsi:type=”axl:XIPPhone” ctiid=”203849429″ uuid=”{96f8508b-10ef-f98c-d20d-0471777ec725}”>
<fullConfig>true</fullConfig>
<deviceProtocol>SIP</deviceProtocol>
<sshUserId></sshUserId>
<sshPassword></sshPassword>
<devicePool uuid=”{a755aa55-089c-2b47-9603-c7d51b9ca4b5}”>
<dateTimeSetting uuid=”{9ec4850a-7748-11d3-bdf0-00108302ead1}”>
<dateTemplate>M/D/Y</dateTemplate>
<timeZone>Greenwich Standard Time</timeZone>
</dateTimeSetting>
<callManagerGroup>
<tftpDefault>true</tftpDefault>
<members>
<member priority=”0″>
<callManager>
<name>ccm-beta-5-1</name>
<description>CallManager 5.0 Beta Pub – 5.0.1.032</description>
<ports>
<ethernetPhonePort>2000</ethernetPhonePort>
<sipPort>5060</sipPort>
<securedSipPort>5061</securedSipPort>
<mgcpPorts>
<listen>2427</listen>
<keepAlive>2428</keepAlive>
</mgcpPorts>
</ports>
<processNodeName>ccm-beta-5-1</processNodeName>
</callManager>
</member>
</members>
</callManagerGroup>
<srstInfo uuid=”{cd241e11-4a58-4d3d-9661-f06c912a18a3}”>
<name>Disable</name>
<srstOption>Disable</srstOption>
<userModifiable>false</userModifiable>
<ipAddr1></ipAddr1>
<port1>2000</port1>
<ipAddr2></ipAddr2>
<port2>2000</port2>
<ipAddr3></ipAddr3>
<port3>2000</port3>
<sipIpAddr1>IP ADDRESS TO SIP SERVER</sipIpAddr1>
<sipPort1>5060</sipPort1>
<sipIpAddr2></sipIpAddr2>
<sipPort2>5060</sipPort2>
<sipIpAddr3></sipIpAddr3>
<sipPort3>5060</sipPort3>
<isSecure>false</isSecure>
</srstInfo>
<mlppDomainId>-1</mlppDomainId>
<mlppIndicationStatus>Default</mlppIndicationStatus>
Default
<connectionMonitorDuration>120</connectionMonitorDuration>
</devicePool>
<sipProfile>
<sipProxies>
<backupProxy>USECALLMANAGER</backupProxy>
<backupProxyPort>5060</backupProxyPort>
<emergencyProxy>USECALLMANAGER</emergencyProxy>
<emergencyProxyPort>5060</emergencyProxyPort>
<outboundProxy>USECALLMANAGER</outboundProxy>
<outboundProxyPort>5060</outboundProxyPort>
<registerWithProxy>true</registerWithProxy>
</sipProxies>
<sipCallFeatures>
<cnfJoinEnabled>true</cnfJoinEnabled>
<callForwardURI>x-cisco-serviceuri-cfwdall</callForwardURI>
<callPickupURI>x-cisco-serviceuri-pickup</callPickupURI>
<callPickupListURI>x-cisco-serviceuri-opickup</callPickupListURI>
<callPickupGroupURI>x-cisco-serviceuri-gpickup</callPickupGroupURI>
<meetMeServiceURI>x-cisco-serviceuri-meetme</meetMeServiceURI>
<abbreviatedDialURI>x-cisco-serviceuri-abbrdial</abbreviatedDialURI>
<rfc2543Hold>false</rfc2543Hold>
<callHoldRingback>2</callHoldRingback>
<localCfwdEnable>true</localCfwdEnable>
<semiAttendedTransfer>true</semiAttendedTransfer>
<anonymousCallBlock>2</anonymousCallBlock>
<callerIdBlocking>2</callerIdBlocking>
<dndControl>0</dndControl>
<remoteCcEnable>true</remoteCcEnable>
</sipCallFeatures>
<sipStack>
<sipInviteRetx>6</sipInviteRetx>
<sipRetx>10</sipRetx>
<timerInviteExpires>180</timerInviteExpires>
<timerRegisterExpires>3600</timerRegisterExpires>
<timerRegisterDelta>5</timerRegisterDelta>
<timerKeepAliveExpires>120</timerKeepAliveExpires>
<timerSubscribeExpires>120</timerSubscribeExpires>
<timerSubscribeDelta>5</timerSubscribeDelta>
<timerT1>500</timerT1>
<timerT2>4000</timerT2>
<maxRedirects>70</maxRedirects>
<remotePartyID>true</remotePartyID>
<userInfo>None</userInfo>
</sipStack>
<autoAnswerTimer>1</autoAnswerTimer>
<autoAnswerAltBehavior>false</autoAnswerAltBehavior>
<autoAnswerOverride>true</autoAnswerOverride>
<transferOnhookEnabled>false</transferOnhookEnabled>
<enableVad>false</enableVad>
none
<dtmfAvtPayload>101</dtmfAvtPayload>
<dtmfDbLevel>3</dtmfDbLevel>
<dtmfOutofBand>avt</dtmfOutofBand>
<alwaysUsePrimeLine>false</alwaysUsePrimeLine>
<alwaysUsePrimeLineVoiceMail>false</alwaysUsePrimeLineVoiceMail>
<kpml>3</kpml>
<phoneLabel></phoneLabel>
<stutterMsgWaiting>2</stutterMsgWaiting>
<callStats>false</callStats>
<offhookToFirstDigitTimer>15000</offhookToFirstDigitTimer>
<silentPeriodBetweenCallWaitingBursts>10</silentPeriodBetweenCallWaitingBursts>
<disableLocalSpeedDialConfig>true</disableLocalSpeedDialConfig>
<startMediaPort>16384</startMediaPort>
<stopMediaPort>32766</stopMediaPort>
<sipLines>
<line button=”1″>
<featureID>9</featureID>
<featureLabel></featureLabel>
<proxy>USECALLMANAGER</proxy>
<port>5060</port>
<name>3302</name>
<displayName>3302</displayName>
<autoAnswer>
<autoAnswerEnabled>2</autoAnswerEnabled>
</autoAnswer>
<callWaiting>3</callWaiting>
<authName></authName>
<sharedLine>false</sharedLine>
<messageWaitingLampPolicy>3</messageWaitingLampPolicy>
<messagesNumber></messagesNumber>
<ringSettingIdle>4</ringSettingIdle>
<ringSettingActive>5</ringSettingActive>
<contact>7b452e87-4496-4762-e11f-b26751a1884b</contact>
<forwardCallInfoDisplay>
<callerName>true</callerName>
<callerNumber>false</callerNumber>
<redirectedNumber>false</redirectedNumber>
<dialedNumber>true</dialedNumber>
</forwardCallInfoDisplay>
</line>
</sipLines>
<voipControlPort>5060</voipControlPort>
<dscpForAudio>184</dscpForAudio>
<ringSettingBusyStationPolicy>0</ringSettingBusyStationPolicy>
<dialTemplate></dialTemplate>
<softKeyFile>SK50719900-3bee-4594-bc3f-6400e1a33bf0.xml</softKeyFile>
</sipProfile>
<commonProfile>
<phonePassword></phonePassword>
<backgroundImageAccess>true</backgroundImageAccess>
<callLogBlfEnabled>2</callLogBlfEnabled>
</commonProfile>
<loadInformation>SIP70.8-0-3S</loadInformation>
<vendorConfig>
<disableSpeaker>false</disableSpeaker><disableSpeakerAndHeadset>false</disableSpeakerAndHeadset><pcPort>0</pcPort><settingsAccess>1</settingsAccess><garp>0</garp><voiceVlanAccess>0</voiceVlanAccess><videoCapability>0</videoCapability><autoSelectLineEnable>0</autoSelectLineEnable><webAccess>0</webAccess><daysDisplayNotActive>1,7</daysDisplayNotActive><displayOnTime>07:30</displayOnTime><displayOnDuration>10:30</displayOnDuration><displayIdleTimeout>01:00</displayIdleTimeout><spanToPCPort>1</spanToPCPort></vendorConfig>
<versionStamp>1136931633-57191cee-5ffc-4342-b286-4246b4991890</versionStamp>
<userLocale>
<name>English_United_States</name>
<uid>1</uid>
<langCode>en_US</langCode>
<version>1.0.0.0-1</version>
<winCharSet>iso-8859-1</winCharSet>
</userLocale>
<networkLocale>United_States</networkLocale>
<networkLocaleInfo>
<name>United_States</name>
<uid>64</uid>
<version>1.0.0.0-1</version>
</networkLocaleInfo>
<deviceSecurityMode>1</deviceSecurityMode>
<idleTimeout>0</idleTimeout>
<authenticationURL>http://ccm-beta-5-1:8080/ccmcip/authenticate.jsp</authenticationURL>
<directoryURL>http://ccm-beta-5-1:8080/ccmcip/xmldirectory.jsp</directoryURL>
<idleURL></idleURL>
<informationURL>http://ccm-beta-5-1:8080/ccmcip/GetTelecasterHelpText.jsp</informationURL>
<messagesURL></messagesURL>
<proxyServerURL></proxyServerURL>
<servicesURL>http://10.86.5.102/CiscoServices/index.xml</servicesURL>
<dscpForSCCPPhoneConfig>96</dscpForSCCPPhoneConfig>
<dscpForSCCPPhoneServices>0</dscpForSCCPPhoneServices>
<dscpForCm2Dvce>96</dscpForCm2Dvce>
<transportLayerProtocol>4</transportLayerProtocol>
<capfAuthMode>0</capfAuthMode>
<capfList>
<capf>
<phonePort>3804</phonePort>
<processNodeName>ccm-beta-5-1</processNodeName>
</capf>
</capfList>
<certHash></certHash>
<encrConfig>false</encrConfig>
<line button=”3″>
<featureID>2</featureID>
<featureLabel>2000</featureLabel>
<speedDialNumber>2000</speedDialNumber>
</line>
<natReceivedProcessing>true</natReceivedProcessing>
<natEnabled>true</natEnabled>
<natAddress></natAddress>
<dialTemplate>dialplan.xml</dialTemplate>
</device>

On the Asterisk server, you will have a file named sip.conf and to have the Cisco IP Phone talking to Asterisk you need this

[999999999]
username=999999999
type=friend
secret=password
nat=no
host=dynamic
canreinvite=no
dtmfmode=rfc2833
context=incoming
qualify=yes
disallow=all
allow=ulaw

That should be it, good luck!

Port Mirroring on Cisco – Monitoring the network

Thursday, May 14th, 2009

“We just bought a new IPS/IDS, just put it between us and our transit provider!”. Sounds slick, huh? This request seems easy, but do you really know if it will function like expected and not jam all network traffic?

Try it out on a mirrored (SPAN) port first! With a SPAN you can get a copy of all traffic from/to a port output on a second port, without interacting with traffic. This can be very helpful if you want to test out some new equipment for Intrusion detection and/or prevention. Snort is an open source alternative for monitoring network traffic for obscurity and irregularities.

To configure a SPAN on 2940, 2950, 2955, 2960, 2970, 3550, 3560 and 3750 switches

Switch#conf t
Switch(config)#monitor session 1 source interface Fa0/18
Switch(config)#monitor session 1 destination interface Fa0/2
Switch(config)#

With the configuration above you will copy all traffic from FastEthernet 0/18 and output it to FastEthernet 0/2
The Cisco Catalyst 2950 is incapable to monitor vlans, but this is possible on for example the Cisco 3750.

To verify a SPAN session

Switch#sh monitor session 1
Session 1
———
Source Ports:
RX Only: None
TX Only: None
Both: Fa0/18
Destination Ports: Fa0/2

I hope this maybe encourages you to test out some applications or equipment that you’ve been wanting to try but haven’t had the guts to!

Manipulate Routed Traffic With A Route-map

Wednesday, May 6th, 2009

Sometimes.. when everything is failing, you’ll need to do some dirty hacks to get things the way you want. I’m going to show you how to modify the next-hop (where the packet is routed) with a route-map

Let’s say you want to redirect web-traffic to a local cache running for example squid, but let other traffic pass on to its intended destination. As usual I have created an imaginary scenario, but this time I have used my creative skills (yeah, right!) to draw a little network map in dia also.

squidroutemap

The idea is to let all TCP port 80 traffic from all the clients to be sent to the web cache server on 10.0.0.2
To achieve this, we need to create an access-list to match web traffic from the clients.

Router#conf t
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#ip access-list extended webtraffic
Router(config-ext-nacl)#deny tcp host 10.0.0.2 any eq www
Router(config-ext-nacl)#permit tcp 10.0.0.0 0.0.0.255 any eq www

To verify that this access-list now exists, run this command

Router#sh ip access-list webtraffic
Extended IP access list webtraffic
10 deny tcp host 10.0.0.2 any eq www
20 permit tcp 10.0.0.0 0.0.0.255 any eq www

As you can see, I have a deny on 10.0.0.2, this is because we can’t match traffic coming from the web caching server and redirect it to itself, that would create a loop.

The next thing we need to do is to create a route-map which uses the webtraffic access-list to match packets and do the intended modifications to it.

Router(config)#route-map webcache-redirect permit 10
Router(config-route-map)#match ip address webtraffic
Router(config-route-map)#set ip next-hop 10.0.0.2
Router(config-route-map)#route-map webcache-redirect permit 200

You can now verify this route-map by doing this

Router#sh route-map webcache-redirect
route-map webcache-redirect, permit, sequence 10
Match clauses:
ip address (access-lists): webtraffic
Set clauses:
ip next-hop 10.0.0.2
Policy routing matches: 0 packets, 0 bytes
route-map webcache-redirect, permit, sequence 200
Match clauses:
Set clauses:
Policy routing matches: 0 packets, 0 bytes

The last thing that needs to be done for this to have effect is to apply policy routing on the interface on which you receive the traffic from the clients (the interface which acts as a gateway for the clients, in this case the one with the IP address 10.0.0.1).

Router(config)#int vlan 1
Router(config-if)#ip policy route-map webtraffic-redirect

You can now use the sh route-map command again to see that your webtraffic now is being policy-routed.

Read about how to setup a squid as a transparent proxy here.

UPDATE: Eirik Hjelle poked me and told me that the squid tutorial that I am refering to is outdated, and it sure is!
The basics of the squid.conf should be (was not going to cover it here, since it’s a cisco blog, but since Eirik was a nice fellow and just gave me a paste of the required I’ll include it:

http_port 3128 transparent
acl internal_network src 10.0.0.0/24
http_access allow internal_network

The traffic will still be directed to port 80 so it might be needed to change the http_port to

http_port 10.0.0.2:80 transparent

Using Tcpdump in Linux to Analyze Network Traffic

Wednesday, February 25th, 2009

Have you ever needed to see traffic in front of your eyes? There exists a tool in linux to do this. You can see it all, even .. passwords.

I will just give you the commands to see different types of traffic, use it for what you want.
You will not see network traffic going between other devices on the network, only to your workstation – assuming you are on a switched network, on a WLAN things are different.
If you want to monitor a network port, you can use a ‘mirror port’ in Cisco, configuration is as follows:

monitor session 1 source interface fastethernet 0/1
monitor session 1 destination interface fastethernet 0/2 encap ingress vlan 1

This will mirror all network traffic on FastEthernet 0/1 to FastEthernet 0/2.
There also exists methods for injecting ARP to a switched network to make network devices believe you are the gateway, so that you can inspect the packets before passing them on to the gateway.

Tcpdump commands
So back to tcpdump, to look at for example web traffic
Always remember that if you want to see the traffic as ASCII, just apply the argument ‘-A’ to tcpdump

I am assuming you are using eth0, -n turns off DNS.

tcpdump -i eth0 -n port 80

Now a little more fancy, using egrep – this will show all your web requests in real time!

tcpdump -i eth0 -A -n port 80 | egrep -i \(GET.\/\|POST.\/\|Host:\)

Did you know you can tcpdump for a subnet by just excluding the last octet?

tcpdump -i eth0 -n port 80 and host 10.0.5

You can see I used ‘and’ here to specify more filter, you can also use or
For example port 80 or port 81

If you forgot your pop3 password, but have it stored in the client

tcpdump -i eth0 -n port 110 -A | egrep -i \(user\|pass\)

This also applies to passwords for the web, I have used this a lot instead of the ‘forgot password’ mechanism.

If I forgot to mention anything, please let me know.

How to setup a GRE tunnel on a Cisco Router

Tuesday, January 13th, 2009

Hey peeps, it has been a while now…
Sorry about that, I have had a lot of things on my mind lately.
Sometimes I also have issues figuring about a new subject to write about, but I will try to take on more advanced networking as someone requested it per email.  If you want me to write about something or need help with anything, don’t hesitate to contact me.

So, let’s warm up the new year with an easy tutorial on how to setup a GRE tunnel on a Cisco router.

Consider this scenario:
Router1 = 172.16.1.1
Router2 = 192.168.0.1

The routing between these routers are fixed so that they can reach each other, like on the internet.
Router2 will have the network 10.0.10.0/24 routed to it via a GRE tunnel.
The address on the tunnel interfaces will be 10.0.0.1 and 10.0.0.2 for Router1 and Router2 respectively.

Router1 configuration:

Router1(config)#interface Tunnel 0
Router1(config-if)#tunnel source 172.16.1.1
Router1(config-if)#tunnel destination 192.168.0.1
Router1(config-if)#tunnel mode gre ip
Router1(config-if)#ip address 10.0.0.1 255.255.255.252
Router1(config-if)#no shutdown
Router1(config-if)#exit
Router1(config)#ip route 10.0.10.0 255.255.255.0 10.0.0.2

Router1(config)#interface Tunnel 0
Router1(config-if)#tunnel source 192.168.0.1
Router1(config-if)#tunnel destination 172.16.1.1
Router1(config-if)#tunnel mode gre ip
Router1(config-if)#ip address 10.0.0.2 255.255.255.252
Router1(config-if)#no shutdown
Router1(config-if)#exit
Router1(config)#ip route 10.0.10.0 255.255.255.0 Null 0

You can now setup addresses within 10.0.10.0/24 on any interface you want and use them like as they were routed to your router directly.
The traceroute from Router2 to Router1 should look something like this:

Router2#traceroute 10.0.0.1

Type escape sequence to abort.
Tracing the route to 10.0.0.1

1 10.0.0.1 8 msec 8 msec 8 msec

Voila, we got routing over GRE!

Cisco IOS Dialin VPN Configuration With Radius Users in MySQL

Monday, November 24th, 2008

Sometimes it can be preferable to have client initiated dialin tunneling, here’s a flexible solution!

First off, the tunnel endpoint configuration (for example a 7200 router)

Router#conf t
Router(config)#aaa group server radius dialin
Router(config-sg-radius)#server-private 10.0.0.5 auth-port 1812 acct-port 1813 key MYSECRET
Router(config-sg-radius)#server 10.0.0.5 auth-port 1812 acct-port 1813
Router(config-sg-radius)#exit
Router(config)#aaa authentication ppp default group dialin
Router(config)#aaa authorization network default group dialin
Router(config)#aaa accounting network default start-stop group dialin
Router(config)#vpdn enable
Router(config)#vpdn authorize directed-request
Router(config)#vpdn-group dialingroup
Router(config-vpdn)#accept-dialin
Router(config-vpdn-acc-in)#protocol l2tp
Router(config-vpdn-acc-in)#virtual-template 1
Router(config-vpdn-acc-in)#exit
Router(config-vpdn)#source-ip 10.0.0.1
Router(config-vpdn)#local name vpnrouter
Router(config-vpdn)#lcp renegotiation always
Router(config-vpdn)#no l2tp tunnel authentication
Router(config-vpdn)#ip mtu adjust
Router(config-vpdn)#interface loopback 5
Router(config-if)#description Loopback for VPDN clients
Router(config-if)#ip address 10.0.1.1 255.255.255.0
Router(config-if)#interface virtual-template 1
Router(config-if)#ip unnumbered Loopback5
Router(config-if)#ip tcp adjust-mss 1420
Router(config-if)#ip policy route-map clear-df
Router(config-if)#peer default ip address pool dialinpool
Router(config-if)#no keepalive
Router(config-if)#ppp mru match
Router(config-if)#ppp authentication pap chap
Router(config-if)#exit
Router(config)#ip local pool dialinpool 10.0.1.2 10.0.1.254

Now, we need the radius server on 10.0.0.5 to work
I installed this on a debian system, the freeradius version used there was 1.1.7-1build4

Just run this command as root to install Freeradius and MySQL

apt-get install freeradius-mysql freeradius mysql-server-5.0

You may need to edit /etc/freeradius/radiusd.conf to have the modules pap and chap loaded if the part is commented out. (the # in the beginning of the lines (not comments) should be removed)

You may also need to remove the comment for

$INCLUDE ${confdir}/sql.conf

Example /etc/freeradius/sql.conf

sql {
driver = “rlm_sql_mysql”
server = “localhost”
login = “freeradius”
password = “mysqlpassword”
radius_db = “radius”
acct_table1 = “radacct”
acct_table2 = “radacct”
postauth_table = “radpostauth”
authcheck_table = “radcheck”
authreply_table = “radreply”
groupcheck_table = “radgroupcheck”
groupreply_table = “radgroupreply”
usergroup_table = “usergroup”
nas_table = “nas”
deletestalesessions = yes
sqltrace = yes
sqltracefile = ${logdir}/sqltrace.sql
num_sql_socks = 5
connect_failure_retry_delay = 60
sql_user_name = “%{Stripped-User-Name}”
# I know my blog design bugs here
authorize_group_check_query = “SELECT ${groupcheck_table}.id,${groupcheck_table}.GroupName,${groupcheck_table}.Attribute,${groupcheck_table}.Value,${groupcheck_table}.op FROM ${groupcheck_table},${usergroup_table} WHERE ${usergroup_table}.UserName = ‘%{SQL-User-Name}’ AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName ORDER BY ${groupcheck_table}.id”
authorize_group_reply_query = “SELECT ${groupreply_table}.id,${groupreply_table}.GroupName,${groupreply_table}.Attribute,${groupreply_table}.Value,${groupreply_table}.op FROM ${groupreply_table},${usergroup_table} WHERE ${usergroup_table}.UserName = ‘%{SQL-User-Name}’ AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName ORDER BY ${groupreply_table}.id”
accounting_onoff_query = “UPDATE ${acct_table1} SET AcctStopTime=’%S’, AcctSessionTime=unix_timestamp(‘%S’) – unix_timestamp(AcctStartTime), AcctTerminateCause=’%{Acct-Terminate-Cause}’, AcctStopDelay = ‘%{Acct-Delay-Time}’ WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= ‘%{NAS-IP-Address}’ AND AcctStartTime <= '%S'" accounting_update_query = "UPDATE ${acct_table1} \ SET FramedIPAddress = '%{Framed-IP-Address}', \ AcctSessionTime = '%{Acct-Session-Time}', \ AcctInputOctets = '%{Acct-Input-Octets}', \ AcctOutputOctets = '%{Acct-Output-Octets}' \ WHERE AcctSessionId = '%{Acct-Session-Id}' \ AND UserName = '%{SQL-User-Name}' \ AND NASIPAddress= '%{NAS-IP-Address}'" accounting_update_query_alt = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S',INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0')" accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', '%S', '0', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0')" accounting_start_query_alt = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'" accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'" accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S', INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}')" simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0" postauth_query = "INSERT into ${postauth_table} (id, user, pass, reply, date) values ('', '%{User-Name}', '%{User-Password:-Chap-Password}', '%{reply:Packet-Type}', NOW())" }

Also this is done in /etc/freeradius/proxy.conf

realm mydsl.com {
type = radius
authhost = LOCAL
accthost = LOCAL
}

Now get the SQL database up and running, login to the MySQL CLI as root and do:

mysql> CREATE DATABASE `radius`;
Query OK, 1 row affected (0.03 sec)
mysql> GRANT ALL PRIVILEGES ON `radius`.* to ‘radius’@’localhost’ IDENTIFIED BY ‘mysqlpassword’;
Query OK, 0 rows affected (0.03 sec)
mysql> USE radius;
Database changed

Then these tables needs to be created

CREATE TABLE `nas` (
`id` int(10) NOT NULL auto_increment,
`nasname` varchar(128) NOT NULL,
`shortname` varchar(32) default NULL,
`type` varchar(30) default ‘other’,
`ports` int(5) default NULL,
`secret` varchar(60) NOT NULL default ‘secret’,
`community` varchar(50) default NULL,
`description` varchar(200) default ‘RADIUS Client’,
PRIMARY KEY (`id`),
KEY `nasname` (`nasname`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `radacct` (
`RadAcctId` bigint(21) NOT NULL auto_increment,
`AcctSessionId` varchar(32) NOT NULL default ”,
`AcctUniqueId` varchar(32) NOT NULL default ”,
`UserName` varchar(64) NOT NULL default ”,
`Realm` varchar(64) default ”,
`NASIPAddress` varchar(15) NOT NULL default ”,
`NASPortId` varchar(15) default NULL,
`NASPortType` varchar(32) default NULL,
`AcctStartTime` datetime NOT NULL default ‘0000-00-00 00:00:00’,
`AcctStopTime` datetime NOT NULL default ‘0000-00-00 00:00:00’,
`AcctSessionTime` int(12) default NULL,
`AcctAuthentic` varchar(32) default NULL,
`ConnectInfo_start` varchar(50) default NULL,
`ConnectInfo_stop` varchar(50) default NULL,
`AcctInputOctets` bigint(20) default NULL,
`AcctOutputOctets` bigint(20) default NULL,
`CalledStationId` varchar(50) NOT NULL default ”,
`CallingStationId` varchar(50) NOT NULL default ”,
`AcctTerminateCause` varchar(32) NOT NULL default ”,
`ServiceType` varchar(32) default NULL,
`FramedProtocol` varchar(32) default NULL,
`FramedIPAddress` varchar(15) NOT NULL default ”,
`AcctStartDelay` int(12) default NULL,
`AcctStopDelay` int(12) default NULL,
`XAscendSessionSvrKey` varchar(10) default NULL,
PRIMARY KEY (`RadAcctId`),
KEY `UserName` (`UserName`),
KEY `FramedIPAddress` (`FramedIPAddress`),
KEY `AcctSessionId` (`AcctSessionId`),
KEY `AcctUniqueId` (`AcctUniqueId`),
KEY `AcctStartTime` (`AcctStartTime`),
KEY `AcctStopTime` (`AcctStopTime`),
KEY `NASIPAddress` (`NASIPAddress`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `radcheck` (
`id` int(11) unsigned NOT NULL auto_increment,
`UserName` varchar(64) NOT NULL default ”,
`Attribute` varchar(32) NOT NULL default ”,
`op` char(2) NOT NULL default ‘==’,
`Value` varchar(253) NOT NULL default ”,
PRIMARY KEY (`id`),
KEY `UserName` (`UserName`(32))
) ENGINE=MyISAM AUTO_INCREMENT=374 DEFAULT CHARSET=latin1;

CREATE TABLE `radgroupcheck` (
`id` int(11) unsigned NOT NULL auto_increment,
`GroupName` varchar(64) NOT NULL default ”,
`Attribute` varchar(32) NOT NULL default ”,
`op` char(2) NOT NULL default ‘==’,
`Value` varchar(253) NOT NULL default ”,
PRIMARY KEY (`id`),
KEY `GroupName` (`GroupName`(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `radgroupreply` (
`id` int(11) unsigned NOT NULL auto_increment,
`GroupName` varchar(64) NOT NULL default ”,
`Attribute` varchar(32) NOT NULL default ”,
`op` char(2) NOT NULL default ‘=’,
`Value` varchar(253) NOT NULL default ”,
PRIMARY KEY (`id`),
KEY `GroupName` (`GroupName`(32))
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

CREATE TABLE `radippool` (
`id` int(11) unsigned NOT NULL auto_increment,
`pool_name` varchar(30) NOT NULL,
`FramedIPAddress` varchar(15) NOT NULL default ”,
`NASIPAddress` varchar(15) NOT NULL default ”,
`CalledStationId` varchar(30) NOT NULL,
`CallingStationID` varchar(30) NOT NULL,
`expiry_time` datetime NOT NULL default ‘0000-00-00 00:00:00’,
`username` varchar(64) NOT NULL default ”,
`pool_key` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `radpostauth` (
`id` int(11) NOT NULL auto_increment,
`user` varchar(64) NOT NULL default ”,
`pass` varchar(64) NOT NULL default ”,
`reply` varchar(32) NOT NULL default ”,
`date` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `radreply` (
`id` int(11) unsigned NOT NULL auto_increment,
`UserName` varchar(64) NOT NULL default ”,
`Attribute` varchar(32) NOT NULL default ”,
`op` char(2) NOT NULL default ‘=’,
`Value` varchar(253) NOT NULL default ”,
PRIMARY KEY (`id`),
KEY `UserName` (`UserName`(32))
) ENGINE=MyISAM AUTO_INCREMENT=1974 DEFAULT CHARSET=latin1;

CREATE TABLE `usergroup` (
`UserName` varchar(64) NOT NULL default ”,
`GroupName` varchar(64) NOT NULL default ”,
`priority` int(11) NOT NULL default ‘1’,
KEY `UserName` (`UserName`(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

# This is the replies that every user that belongs to the group ‘clients‘ will receive
INSERT INTO `radgroupreply` VALUES (1,’clients’,’Service-Type’,’:=’,’Framed-User’)
INSERT INTO `radgroupreply` VALUES (2,’clients’,’Framed-Protocol’,’:=’,’PPP’)
INSERT INTO `radgroupreply` VALUES (3,’clients’,’Framed-Routing’,’:=’,’Broadcast-Listen’),
INSERT INTO `radgroupreply` VALUES (4,’clients,’Framed-MTU’,’:=’,’1420′)
INSERT INTO `radgroupreply` VALUES (5,’clients’,’Framed-Compression’,’:=’,’Van-Jacobsen-TCP-IP’);

# This creates a user with username ‘testuser’ and password ‘testpassword’
INSERT INTO `radcheck` VALUES (1,’testuser’,’User-Password’,’:=’,’testpassword’);

# This assigns 10.0.1.2 to the user ‘testuser’
INSERT INTO `radreply` VALUES (1,’testuser’,’Framed-IP-Address’,’:=’,’10.0.1.2′)

# This adds the user ‘testuser’ to the group ‘clients’, then it will receive all correct attributes from radgroupreply.
INSERT INTO `usergroup` VALUES (‘testuser’,’clients’,1);

Now just restart MySQL and Freeradius and the only thing left to do is to configure the VPDN client.

This is configured on a Cisco 850 series router with the WAN link on FastEthernet 4

Client#conf t
Client(config)#ip domain name mydsl.com
Client(config)#l2tp-class l2tpclass1
Client(config)#pseudowire-class pwclass1
Client(config-pw-class)#encapsulation l2tpv2
Client(config-pw-class)#protocol l2tpv2 l2tpclass1
Client(config-pw-class)#ip local interface FastEthernet4
Client(config-pw-class)#interface virtual-ppp 1
Client(config-if)#ip address negotiated
Client(config-if)#ip tcp adjust-mss 1420
Client(config-if)#ip policy route-map clear-df
Client(config-if)#ppp authentication pap chap callin
Client(config-if)#ppp chap hostname testuser@mydsl.com
Client(config-if)#ppp chap password testpassword
Client(config-if)#ppp pap sent-username testuser@mydsl.com password testpassword
Client(config-if)#ppp ipcp route default
Client(config-if)#pseudowire 10.0.0.1 10 pw-class pwclass1

That should be about it! Don’t be afraid of the comment box!

Configuring MySQL AAA Authentication and Accounting with Tacacs+ on Linux

Monday, November 10th, 2008

So, been experimenting more with tacacs+ and got everything working out nicely with MySQL – so here is my tutorial!

It seemed like I had to run out of my “Oh, I run ubuntu so I will just apt-get” luck sometime, as I actually had to take this one from source to make it work completely.
So I will start with the Linux end of this, the compiling of tac_plus

If you followed my previous tutorial, you will have to remove the old tac_plus package.

root@server:~# apt-get remove tac-plus
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages will be REMOVED:
tac-plus
0 upgraded, 0 newly installed, 1 to remove and 104 not upgraded.
Need to get 0B of archives.
After unpacking 324kB disk space will be freed.
Do you want to continue [Y/n]?
(Reading database … 227395 files and directories currently installed.)
Removing tac-plus …
Stopping Tacacs+ server: tac_plus.
root@server:~# dpkg –purge tac-plus

The dpkg –purge command will remove all configuration files, so if you want to keep them just run

root@server:~# cp -r /etc/tac-plus /root/tac-plus-configuration

This will store the old configuration files in a folder named /root/tac-plus-configuration

Now compile the tac_plus daemon, remember to have the libmysql++-dev installed before you do this. It should also bring along libmysql++2c2a libmysqlclient15-dev by itself.

root@server:~# cd /usr/local/src
root@server:/usr/local/src# wget -q http://www.gho.no/download/tac_plus-4.4.tgz
root@server:/usr/local/src# tar -zxf tac_plus-4.4.tgz
root@server:/usr/local/src# cd tac_plus-4.4
root@server:/usr/local/src/tac_plus-4.4# wget -q http://www.gho.no/download/securid.tgz
root@server:/usr/local/src/tac_plus-4.4# tar -zxf securid.tgz
root@server:/usr/local/src/tac_plus-4.4# ./configure –with-mysql –with-db

It should now print a lot of ‘checking for’ or ‘checking wheter’ lines, just let it run.
The last couple of lines you should see should be:

creating Makefile
creating tac_plus.spec
creating config.h
config.h is unchanged

Then it’s time to run make to compile the source code into a binary file.

root@server:/usr/local/src/tac_plus-4.4# make
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c acct.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c authen.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c author.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c config.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c choose_authen.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c default_fn.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c default_v0_fn.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c do_acct.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c do_author.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c dump.c
dump.c: In function ‘dump_nas_pak’:
dump.c:159: warning: incompatible implicit declaration of built-in function ‘exit’
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c enable.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c encrypt.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c expire.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c hash.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c tac_plus.c
tac_plus.c: In function ‘main’:
tac_plus.c:364: warning: incompatible implicit declaration of built-in function ‘exit’
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c md5.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c packet.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c parse.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c programs.c
programs.c: In function ‘my_popen’:
programs.c:282: warning: incompatible implicit declaration of built-in function ‘exit’
programs.c:287: warning: incompatible implicit declaration of built-in function ‘exit’
programs.c:292: warning: incompatible implicit declaration of built-in function ‘exit’
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c pw.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c pwlib.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c report.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c sendauth.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c sendpass.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c time_limit.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c utils.c
utils.c: In function ‘tac_exit’:
utils.c:79: warning: incompatible implicit declaration of built-in function ‘exit’
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c accesslog.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c ext_authen.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c db.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c db_ext.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c db_null.c
gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/mysql -g -O2 -c db_mysql.c
gcc -g -O2 -L/usr/lib/mysql -o tac_plus -L/usr/lib/mysql acct.o authen.o author.o config.o choose_authen.o default_fn.o default_v0_fn.o do_acct.o do_author.o dump.o enable.o encrypt.o expire.o hash.o tac_plus.o md5.o packet.o parse.o programs.o pw.o pwlib.o report.o sendauth.o sendpass.o time_limit.o utils.o accesslog.o ext_authen.o db.o db_ext.o db_null.o db_mysql.o -lmysqlclient -lz -lnsl -lpthread -lc -lcrypt -Llib/lnx -laceclnt
root@server:/usr/local/src/tac_plus-4.4# cp tac_plus /usr/sbin/

Now, I just did a quick hack with copying the tac_plus binary to /usr/sbin, if you choose to install it with make install, be aware that it will spread files all around your system that you really don’t need.

I got a library error, this is my fix.

root@server:/usr/local/src/tac_plus-4.4# /usr/sbin/tac_plus -v
/usr/sbin/tac_plus: error while loading shared libraries: libaceclnt.so: cannot open shared object file: No such file or directory
root@server:/usr/local/src/tac_plus-4.4# cp lib/lnx/libaceclnt.so /usr/lib && ldconfig
root@server:/usr/local/src/tac_plus-4.4# /usr/sbin/tac_plus -v
tac_plus version 4.4rc2-3 (Extended Tac_plus)

Perfect, shared libraries installed and the tacacs daemon seems to be working!
Now to create the configuration file and everything.

root@server:/usr/local/src/tac_plus-4.4# cd /etc
root@server:/etc# mkdir tac-plus && chmod 700 tac-plus
root@server:/etc# cd tac-plus
root@server:/etc/tac-plus# touch tacacs.conf && chmod 700 tacacs.conf

Edit the /etc/tacacs.conf file with your favourite editor, I as always love vim.
For simplicity, let us keep it to a small amount of lines.

The contents of /etc/tacacs.conf

key mykey
default db = mysql://tacacs:tacacspassword@localhost/tacacs

The logics of the MySQL URI is mysql://username:password@databasehost/database, so the username will now be tacacs, the password will be ‘password’ and the database ‘tacacs’ on the MySQL server on localhost.

MySQL Setup
We now need to setup the backend databases for tac_plus to communicate with.

root@server:/etc/tac-plus# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11335
Server version: 5.0.38-Ubuntu_0ubuntu1.4-log Ubuntu 7.04 distribution

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql> \. /usr/local/src/tac_plus-4.4/tac_plus.sql
Query OK, 1 row affected (0.36 sec)

Database changed
Query OK, 0 rows affected (0.19 sec)

#… You should get a lot of these lines and return to the prompt, verify the structure:
mysql> show tables;
+——————+
| Tables_in_tacacs |
+——————+
| access |
| accounting |
| acl |
| admin |
| attribute |
| contact_info |
| host |
| node |
| user |
| vendor |
+——————+
10 rows in set (0.08 sec)

# You now need to grant access to tacacs
mysql> GRANT ALL PRIVILEGES ON tacacs.* to tacacs@localhost IDENTIFIED BY ‘tacacspassword’;
Query OK, 0 rows affected (0.00 sec)

You could grant SELECT on the user and host tables, while letting it modify for example only the accounting and access tables which it uses for .. well, accounting records. It records logins/logouts and commands written if you want to. Tac-plus will automagically do this for you, and the Cisco Configuration is well documented in my article about Log Commands on Your Cisco Routers and Switches With Tacacs On Linux. Oh well, let us go on.

Let us insert just a user and a host.

INSERT INTO user (uid, gid, password, expires) values (‘username’, ‘100’, ENCRYPT(‘testtest’), ‘0000-00-00’);
INSERT INTO host (ip, hostgroup, hkey, network, submask, loginacl, host) VALUES (‘10.0.0.5’, ‘Routers’, ‘tercesym’, ‘0’, ‘0’, ‘666’, ‘1’);
INSERT INTO acl (id, type, seq, permission, value, value1, submask) VALUES (‘666’, ‘2’, ‘1’, ’57’, ‘allusers’, ‘0’, ‘0’);

That should be it, we are done with this and we can now start the daemon.

root@server:~# /usr/sbin/tac_plus -C /etc/tac-plus/tacacs.conf -d254 -l tac.log

You can now monitor tac.log which resides in your current working directory (pwd), with tail -f tac.log and you can remove the -d254 when you are sure this is working.
You should now be able to login with user username and password testtest.

To configure your Cisco IOS running Switch or Router

Router(config)#aaa authentication login default local group tacacs+
Router(config)#tacacs-server host 10.0.0.5 key mykey

As long as you keep the ‘local’ in the authentication line, you will still be able to fall back to local user authentication.

If you get any weird errors or warnings, post them as a comment and I will have a look at it!

Log Commands on your Cisco Routers and Switches with Tacacs+ on Linux

Sunday, November 9th, 2008

I setup command logging with Tacacs+ on Linux this week. Let me show you how easy it is!

I am (as always) doing this with Ubuntu linux and so I just have to apt-get the packages I need.

espen@server:~$ sudo apt-get install tac-plus
Password:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following NEW packages will be installed:
tac-plus
0 upgraded, 1 newly installed, 0 to remove and 104 not upgraded.
Need to get 105kB of archives.
After unpacking 324kB of additional disk space will be used.
Get:1 http://no.archive.ubuntu.com feisty/universe tac-plus 1:4.0.4.alpha-14 [105kB]
Fetched 105kB in 0s (331kB/s)
Selecting previously deselected package tac-plus.
(Reading database … 227388 files and directories currently installed.)
Unpacking tac-plus (from …/tac-plus_1%3a4.0.4.alpha-14_i386.deb) …
Adding system user `tacacs’ (UID 64005) …
Adding new group `tacacs’ (GID 64005) …
Adding new user `tacacs’ (UID 64005) with group `tacacs’ …
Not creating home directory `/home/tacacs’.
Setting up tac-plus (4.0.4.alpha-14) …
Starting Tacacs+ server: tac_plus.

Wow, that was quick… The tacacs+ server is already running!
But wait, we have to configure it just a bit.

For this article I will just focus on the logging part (accounting), but I will continue to write about authentication and authorization to fully comply fully with AAA.

Now, open up /etc/tac-plus/tacacs.conf in your favourite editor, mine is vim.
Be sure to uncomment and set the key, set the accounting file and you should be ready to roll.

key = tercesym
accounting file = /var/log/tac-plus/account

Just restart the tacacs daemon:

espen@server:/etc/tac-plus# sudo /etc/init.d/tac-plus restart
Restarting Tacacs+ server: tac_plus.
espen@server:/etc/tac-plus#

Now to configure this on your cisco equipment, please follow the steps in this article first.
Then to make sure the Cisco IOS Switch or Router will notify your tacacs deamon of accounting events, this is the configuration you need.

Router#conf t
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#aaa accounting delay-start
Router(config)#aaa accounting exec default start-stop group tacacs+
Router(config)#aaa accounting commands 15 default start-stop group tacacs+
Router(config)#tacacs-server host 10.0.0.50 key tercesym

! If you want the Router to source from a specific IP address
Router(config)#ip tacacs source-interface Loopback 1

Router(config)#end
Router#

Now you can verify accounting

Router#show accounting

Active Accounted actions on tty1, User admin Priv 1
Task ID 17, EXEC Accounting record, 00:16:58 Elapsed
task_id=17 start_time=1226261207 timezone=CET service=shell

There is one accounting session running, and you can also check the server to see if any accounting records are recorded.

espen@server:~# sudo tail /var/log/tac-plus/account
Sun Nov 9 21:26:58 2008 10.0.0.98 admin tty1 10.0.0.5 stop task_id=26 start_time=1226262225 timezone=CET service=shell priv-lvl=15 cmd=show accounting

Perfect, now there will be no doubt about who dropped that ‘no router bgp’ command on your Cisco Router!