Archive for the 'Uncategorized' Category

23
Jun
15

SSH Jump server in Mac

This config is a pretty common setup it allos one to use a jump server to access all other sevrers seemlesly. In this example my Jump server will be called jump.example.com and the protected serveres will be under the domain *.private.example.com. Without anyconfig i could access a server by doing something like the folllowing

ssh -t jump.example.com ssh server1.private.example.com.

However this is somewhat cumbersome so lets create a config that makes this seemless.

UPDATE: As per the comments you dont need the launchd section. Possible i originally did this so we dont have the cost of establishing an ssh tunnle each time. however with Control persist i doubt ther is much saving. as such the following is all that is needed

Host bastion
  DynamicForward localhost:1080
  HostName jump.example.com
  ProxyCommand none
Host *.private.example.com.
  ProxyCommand ssh bastion nc %h %p
  ServerAliveInterval 10

The first thing we need to do is create a tunnel to jump.exmaple.com, im using mac osx so this will be done in Launchd

#cat ~/Library/LaunchAgents/com.b4ldr.ssh-tunnel.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.b4ldr.ssh-tunnel</string>
  <key>OnDemand</key>
  <false/>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/ssh</string>
    <string>-C</string>
    <string>-N</string>
    <string>-c</string>
    <string>blowfish</string>
    <string>-o</string>
    <string>ServerAliveInterval=3</string>
    <string>bastion</string>
  </array>
</dict>
</plist>

This creates a launchd process which will automatically connect to the server bastion which is defined in my ~/.ssh/config file to act as a socks proxy with the following config, we could put the following config in the launchd job however this allows us to easily change which server is the jump box.

Host bastion
  DynamicForward localhost:1080
  HostName jump.example.com
  ProxyCommand none

Finally we need some config to tell all servers with a domain name of *.private.example.com. to forward its commands via the socks proxy

Host *.private.example.com.
  ProxyCommand nc -x localhost %h %p
  ServerAliveInterval 10

Finnaly load and start the plist

launchctl load ~/Library/LaunchAgents/com.b4ldr.ssh-tunnel.plist
launchctl start com.b4ldr.ssh-tunnel

Hope its useful

Advertisements
30
Sep
14

More useless crap with proc

Im currently on a Security course and one of the tasks we got set today was to create a a small script that would close a port only once a TCP connection had fully established. There was another lab on using nessus which i was suppose to do first but lets be honest nessus isn’t exactly rocket science and this seemed much more fun. It didn’t take long before i hacked something together and came up with the following script

#!/bin/sh
while :
do
  netstat -ant | awk '$6=="ESTABLISHED" {print $4,$5}' | while read IN
  do
    SRC=${IN% *}
    DST=${IN#* }
    if [ "${SRC#*:}" -eq "5555" ]
    then
      echo "Kill: ${DST%:*}"
      iptables -I INPUT -s ${DST%:*} -p tcp --dport ${SRC#*:} -j REJECT --reject-with icmp-host-prohibited
    fi
  done
  sleep 1
  iptables -F
done

However i didn’t really like this because it left the old connection hanging around in the CLOSE_WAIT state. After my previous fairway in to the proc system I wondered if i could improve on the above script by closing the file handle directly. So the first thing to do is fetch the inode associated with the listening port. Previously i used `netstat -tnpo` for this but we shouldn’t need to call a binary to get this information so i decided to just parse the dev system which gave me the following script

#!/bin/bash
PORT=5555
H_PORT=$(echo "obase=16; ${PORT}" | bc)
while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    print "Port: ${SRC#*:}, Inode: ${INODE}
  done
done

Adding this with the hackary from the previous post we can get the associate pid and file handle, we could probably simplify the below as i suspect we could find out the pid in a better manner as we will likely already know the listening PID. Anyway i had the code from before so i may as well use it, this gives us

while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    if [ "${SRC#*:}" == "${H_PORT}" -a ${SRC%:*} != '00000000' ]
    then
      for FD in /proc/*/fd/* ; do
        SOCKET_INODE=$(stat -c  %N ${FD} 2>/dev/null | awk -F\: '/socket:\[[0-9]+\]/ {gsub(/[\[\]]/, "", $NF);print $NF}')
        if [ "${INODE}" == "${SOCKET_INODE%?}" ]
        then
          echo "Kill: ${FD}" 
        fi
      done
    fi
  done
  sleep 1
done

So now all we need to do is kill this file descriptor. A quick google showed this should be pretty simple to do with gdb, however every-time i tried this i kept getting the following error

GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
Attaching to process 16157
Reading symbols from /usr/local/bin/nc...(no debugging symbols found)...done.
(no debugging symbols found)
0x0805c008 in ?? ()
(gdb) p close(4)
No symbol table is loaded.  Use the "file" command.
(gdb) quit
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /usr/local/bin/nc, process 16157

Now im a long way from being a gdb expert but it seemed that nc had not been compiled with the right options, i would have still expected it to be able to preform this function but alas i couldn’t kick it in the right place to make it listen to me. So i thought i would give ncat a go, nc is pretty obsolete anyway and its likely that ncat was compiled with symbols. A quick test and it looked like it worked.

 gdb -p 6592
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
Attaching to process 6592
Reading symbols from /usr/bin/ncat...(no debugging symbols found)...done.
Reading symbols from /lib/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2

(no debugging symbols found)
0x00892416 in __kernel_vsyscall ()
Missing separate debuginfos, use: debuginfo-install nmap.i386
(gdb) p close (4)
$1 = 0
(gdb) quit
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /usr/bin/ncat, process 6592

Awesome now we are in business just a matter of putting it all together and we get the following

#!/bin/bash
PORT=5555
H_PORT=$(echo "obase=16; ${PORT}" | bc)
while :
do
  awk '{print $2,$10}' /proc/net/tcp | while read IN
  do
    SRC=${IN% *}
    INODE=${IN#* }
    if [ "${SRC#*:}" == "${H_PORT}" -a ${SRC%:*} != '00000000' ]
    then
      for FD in /proc/*/fd/* ; do
        SOCKET_INODE=$(stat -c  %N ${FD} 2>/dev/null | awk -F\: '/socket:\[[0-9]+\]/ {gsub(/[\[\]]/, "", $NF);print $NF}')
        if [ "${INODE}" == "${SOCKET_INODE%?}" ]
        then
          PROC=(${FD//\// })
          gdb -p ${PROC[1]} <<< "p close(${PROC[3]})"
        fi
      done
    fi
  done
  sleep 1
done

Unfortunately there is a small problem with this. it seems that been so heavy handed and forcing the file handle to close causes ncat to get into a strange state. new connections seem to be assigned inode 0 and i can’t find a file handle associated with them so it doesn’t really fit the initial use case and means it is pretty useless, although, i think you will agree, it is elegant is its uselessness :). Its worth mentioning that the socket is still open and i can send data through it so its possible this trick may open other avenues we can exploit.

[root@linux ~]# netstat -tnpe
Proto Recv-Q Send-Q Local Address               Foreign Address             State       User       Inode      PID/Program name
tcp        0      0 10.10.75.5:5555             10.10.75.3:57851            ESTABLISHED 0          0          -
tcp        0      0 10.10.75.5:5555             10.10.75.3:57859            ESTABLISHED 0          0          -
[root@linux ~]# tcpdump -nnvvi eth0 port 5555
23:05:04.160869 IP (tos 0x10, ttl 64, id 14484, offset 0, flags [DF], proto TCP (6), length 59)
    10.10.75.3.57851 > 10.10.75.5.5555: Flags [P.], cksum 0x61e0 (correct), seq 111:118, ack 1, win 8235, options [nop,nop,TS val 31297540 ecr 5667926], length 7
23:05:04.160890 IP (tos 0x0, ttl 64, id 7215, offset 0, flags [DF], proto TCP (6), length 52)
    10.10.75.5.5555 > 10.10.75.3.57851: Flags [.], cksum 0xae42 (correct), seq 1, ack 118, win 181, options [nop,nop,TS val 5668951 ecr 31297540], length 0
23:06:59.551591 IP (tos 0x10, ttl 64, id 27876, offset 0, flags [DF], proto TCP (6), length 59)
    10.10.75.3.57859 > 10.10.75.5.5555: Flags [P.], cksum 0xba4f (correct), seq 2737832488:2737832495, ack 2038745254, win 8235, options [nop,nop,TS val 31408622 ecr 5085920], length 7
23:06:59.551611 IP (tos 0x0, ttl 64, id 21062, offset 0, flags [DF], proto TCP (6), length 52)
    10.10.75.5.5555 > 10.10.75.3.57859: Flags [.], cksum 0x6570 (correct), seq 1, ack 7, win 181, options [nop,nop,TS val 5784341 ecr 31408622], length 0
12
May
14

Monitoring Anycast nodes

In my previous article i mentioned the script i was working was intended for an anycast system. So I thought i would expand a bit on what i was working on.

I have operated a couple of anycast clouds and one of the problems one has is ensuring a node is serving correct dns traffic from its anycast address. There are many was to do this and our puppet policies already ensure we do not advertise our anycast prefix unless the dns server is serving correct answers. This ensures the host can answer locally but you are still left wondering if things are working up stream. you can check the unicast address from a remote system which gives you a another pice of incomplete information, although you may not want to listen on your unicast address.

With that in mind i was inspired by a friend to add another pice of incomplete information with a new idea. They had already set up the perl snippet in the aforementioned article. with a monitoring server parsing tcpdumps to preform much of what i describe on github. I have simply tarted things up and wrote things down.

The basic idea is to periodically run a script on each anycast node, this script will spoof the source address of a monitoring server and send a few queries to help us ensure the server is functioning. This allows us to check that responses from a nodes anycast address has a reverse path back to our monitoring server. however we can also use it in place of other checks to ensure serial numbers and other factors are correct.

My [work in progress] solution to this is, is a bunch of tools i have named very badly as dnsreader. I have tried to document examples on that page but feel free to comment if anything is unclear

19
Mar
14

Tracing packet drops

I often find my self tracing where in a network traffic is being dropped. Unfortunately there are not many tools that are able to do this well.  tcptraceroute is pretty good but it doesn’t help with UDP.  Enter scappy.  Below are three small examples of how one can use scapy to trace packets through there network.  

ICMP

ans, unans = sr(IP(dst='192.0.2.1', ttl=(1,24))/ICMP(),timeout=3)
for snd,rcv in ans:
 print snd.ttl, rcv.src

TCP

ans, unans = sr(IP(dst='192.0.2.1', ttl=(1,24))/TCP(dport=6969,sport=53),timeout=3)
for snd,rcv in ans:
 print snd.ttl, rcv.src

UDP

ans, unans = sr(IP(dst='192.0.2.1', ttl=(1,24))/UDP(dport=6969,sport=53),timeout=3)
for snd,rcv in ans:
 print snd.ttl, rcv.src
07
Jun
13

Linux and router advertisements – ignore the prefix

This is just a short one.  I currently working on a project which involves managing a server owned and hosted by multiple different companies.  for me to be able to build the server i need to insist on certain things.  one of these this things is a static ipv6 address.

Now many organisation use Router Advertisements to distribute the default gateway and some use the to dynamically allocate ip addresses.  To my knowledge there is know way of providing a statically mapped address via RA’s.  So you probably know where im going with this.  

The network i was installing in today used RA’s to distribute both a prefix and a default route.  I already have a number of systems that that receive a default route via RA; however known of these networks offers a prefix in the RA.   At this point i could have probably contacted the operator and asked to stop sending out the prefix but where is the fun in that, there must be a way to accept the route and not the prefix.

We use centos so my first search was the [not so] amazingly documented network-scripts to see if there was a special flag i could get to achieve the behaviour i was after.  I found no such variable.  so i decided i would need to set the appropriate kernel parameter in a /sbin/ifup-local script.

The are a number of kernel parameters which we are interested in

accept_ra - BOOLEAN
	Accept Router Advertisements; autoconfigure using them.

	Possible values are:
		0 Do not accept Router Advertisements.
		1 Accept Router Advertisements if forwarding is disabled.
		2 Overrule forwarding behaviour. Accept Router Advertisements
		  even if forwarding is enabled.

	Functional default: enabled if local forwarding is disabled.
			    disabled if local forwarding is enabled.

accept_ra_defrtr - BOOLEAN
	Learn default router in Router Advertisement.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

accept_ra_pinfo - BOOLEAN
	Learn Prefix Information in Router Advertisement.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

accept_ra_rt_info_max_plen - INTEGER
	Maximum prefix length of Route Information in RA.

	Route Information w/ prefix larger than or equal to this
	variable shall be ignored.

	Functional default: 0 if accept_ra_rtr_pref is enabled.
			    -1 if accept_ra_rtr_pref is disabled.

accept_ra_rtr_pref - BOOLEAN
	Accept Router Preference in RA.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

The ones that are really important to use are

accept_ra #needs to be set to 1
accept_ra_defrtr #needs to be set to 1
accept_ra_pinfo #needs to be set to 0

When the network scripts run if IPV6_AUTOCONF=yes then  accept_ra will be set to 1.  this will also cause the other *_ra_* parameters to be set to 1 as documented above.  so the only thing we really need to do is set accept_ra_pinfo to 0.  this is where we use the /sbin/ifup-local script below.

#!/bin/sh
DEVICE="$1"
/sbin/sysctl -e -w net.ipv6.conf.$DEVICE.accept_ra_pinfo=0 >/dev/null 2>&1

Conclusion

if you want router advertisement default gateway but you want to ignore the prefix sent.  Add IPV6_AUTOCONF=yes to your ifcfg-em? file and create /sbin/ifup-local with the above code.

Enjoy

28
Jan
12

HideMyAss VPN Part 3

So now we have our daemons with multiple tunnels so how do we keep them uptodate. Below is the script i use to update the config. it preforms some simple error checking to avoid restarting the tunnels unnecessarily so you could possibly run it from cron

#!/bin/bash

UK_URL="http://vpn.hidemyass.com/vpnconfig/client_config.php?win=1&loc=UK,+London+(LOC1+S1)"
US_URL="http://vpn.hidemyass.com/vpnconfig/client_config.php?win=1&loc=USA,+New+York+(DC2+S1)"
UK_DOMAINS="www.bbc.co.uk www.itv.co.uk mercury.itv.com www.channel4.com ais.channel4.com ll.securestream.channel4.com"
US_DOMAINS="www.hulu.com www.vevo.com www.crackle.com"

declare -A DOMAINS=(["uk"]=${UK_DOMAINS} ["us"]=${US_DOMAINS})
declare -A URL=(["uk"]=${UK_URL} ["us"]=${US_URL})

for COUNTRY in us uk
do
        TMPFILE=`mktemp` || exit 1
        wget "${URL[${COUNTRY}]}" -O ${TMPFILE}  || exit 1
        sed -i -e 's/\.\/keys\//\/etc\/openvpn\/keys\//g' -e 's/^auth-user-pass/auth-user-pass \/etc\/openvpn\/up/' ${TMPFILE}
        echo "route-nopull" >> ${TMPFILE}
        echo "max-routes 10240" >> ${TMPFILE}
        for DOMAIN in ${DOMAINS[${COUNTRY}]}
        do
                echo origin $(dig +short ${DOMAIN} | tail -1)  | \
                nc asn.shadowserver.org 43 | awk '{print "prefix",$1}'  | \
                nc asn.shadowserver.org 43  | \
                while read line
                do  
                        echo -en "route "  
                        ipcalc --nocolor --nobinary ${line}  |  awk '/(Address|Netmask)/ {printf "%s ", $2}'  
                        echo  
                done
        done | sort | uniq >> ${TMPFILE}
        O_HASH=$(md5sum /etc/openvpn/openvpn-${COUNTRY}.cfg | awk '{print $1}')
        N_HASH=$(md5sum ${TMPFILE} | awk '{print $1}')
        if [ "${O_HASH}" != "${N_HASH}" ]
        then 
                echo "${O_HASH}"
                echo "${N_HASH}"
                echo  "/etc/openvpn/openvpn-${COUNTRY}.cfg has changed"
                mv ${TMPFILE}  /etc/openvpn/openvpn-${COUNTRY}.cfg
                svc -d  /service/openvpn-${COUNTRY}
                svc -u  /service/openvpn-${COUNTRY}
        else
                rm  ${TMPFILE}
        fi
done
28
Jan
12

HideMyAss VPN Part 2

In the last post i showed how to create seperate vpns for differnt prefixes. Here i show how to ensure different tunnels come up at boot and remain up.  i use daemontools, ubuntu users are probably best using upstart.

We first need to add auth-user-pass /etc/openvpn/up to the config files. Then create  /etc/openvpn/up with your username and password on separate lines.  and install daemontools.  for this i use yaourt to pull it from AUR.  check here for how to install yaourt https://wiki.archlinux.org/index.php/Yaourt

yaourt -S daemontools

add the following to initab, i put mine after the su line. i had problems when i put it at the end of the file.

sv:123456:respawn:/usr/sbin/svscanboot

create a directory for the two damons, make the run file and link them to /services/

for i in uk us ; do mkdir /etc/openvpn-${i}; echo  '#!/bin/sh' > /etc/openvpn-${i}/run ; echo "exec /usr/sbin/openvpn /etc/openvpn/openvpn-${i}.cfg  1> log.1.out 2> log.2.out" >> /etc/openvpn-${i}/run ; ln -sv /etc/openvpn-${i} /service/; done

reboot. use the following to check you have tun devices and routes for you new vpns

ifconfig ; netstat -rn

check `man svc` and `man svstat` for basic info on daemon tools

The next and last part of this series will show how to keep your tunnels upto date