├── open-ports.service ├── open-ports.timer ├── README.md ├── open_ports_install_linux.sh ├── open_ports_install_os_x.sh ├── LICENSE └── open_ports.sh /open-ports.service: -------------------------------------------------------------------------------- 1 | [Service] 2 | Type=oneshot 3 | ExecStart=/usr/bin/open_ports.sh 4 | -------------------------------------------------------------------------------- /open-ports.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Update open-ports' database 3 | 4 | [Timer] 5 | OnCalendar=*-*-* *:0/2 6 | 7 | [Install] 8 | WantedBy=timers.target 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | open-ports 2 | ========== 3 | 4 | A bash-script for OS X and Linux detailing the open network connections to and from a computer 5 | 6 | ![Screendump of open_ports](http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports/open_ports_2.6.3.png) 7 | 8 | More information about the script can be found here: 9 | http://cs.lth.se/peter-moller/script/open-portssh-en/ 10 | 11 | ----- 12 | 13 | Birds eye view of how the script works: 14 | --------------------------------------- 15 | * When run as root, data is generated and stored on disk 16 | * When run as any other user, data is presented from those files 17 | * Optionally, GeoLookup is done from http://api.db-ip.com (requires a free key) 18 | Result from that is stored on disk to speed up future lookups 19 | * The external address is checked with http://ipecho.net 20 | * IP address (as well as default interface, checked against `www.lu.se`) 21 | 22 | *One clarification: the script **needs** to run as root, or you will only see your own connections and that makes it much less valuable!* 23 | 24 | Other features: 25 | --------------- 26 | * The external IP-address is checked every hour to see if it has been changed 27 | * The age of the data files are checked: if they are older than 1 hour, a warnng is printed 28 | * Once every week the script looks for a new version of itself and notifies the user accordingly 29 | * Every two hours the checksum of the “lsof” binary is checked to look for intrusions: if it has been changed a warning is printed instead of output 30 | * On OS X only: 31 | * lists all interfaces, in priority order 32 | * looks for available software updates every 6 hours 33 | * When the script has been installed, or updated, a “signal” is send to me (a curl to a specific URL that I check for in the apache-log on the dept. server. This is done out of curiosity of how many installs and updates there are, and no information is used in any other way) 34 | 35 | Tha basic functionality of the script can be encapsulated in: 36 | ESTABLISHED connections (Darwin, `IPv4`; replace the `4` with a `6` for `IPv6`): 37 | `lsof +c 0 -i 4 -n | grep EST | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed -e 's/\ [[:digit:]].*-\>/\ /g' -e 's/:/\ /g' | sort -f | uniq -c` 38 | and 39 | LISTEN connections (Darwin, same as above, almost...): 40 | `lsof +c 0 -i 4 -n | grep LISTEN | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print "4 - "$1" "$3" "$9 }' | sed -e 's/:/\ /g' -e 's/\ [[:digit:]]\{2,5\}$/\ anonymous_port/g' | uniq` 41 | For Linux the central lines are almost the same. 42 | 43 | 44 | Operation of the script, in line-order: 45 | ---------------------------------------------------- 46 | 1. Quit if either: 47 | - `open_ports.sh` is already running with the same `$UID` 48 | - the OS is not Darwin or Linux 49 | 2. Functions 50 | 3. Definitions of variables (I'm unsure if they “should” come before the functions, but I'm pretty sure it doesn't matter… :-) 51 | 4. If script is run by `root`, generate data and then exit 52 | 5. Checks: 53 | - is there an update? 54 | - is there a STOP-flag (`lsof` has been changed)? If so, notify user and exit the script 55 | - Is there any data file at all? Warn and exit if not 56 | - If OS X: check to see if the `launchd`-part is running. Warn if not 57 | - Are the data files older than 1 hour? Warn if so 58 | - Do we have an IP address (rather: do we have a default interface – checked against `www.lu.se`)? Warn otherwise 59 | 6. Find out, and print system information 60 | 7. If OS X: look for software updates (this is done every 6 houres; result stored in `/tmp/swu.temp`) 61 | 8. Print the head 62 | 9. Print the ESTABLISHED files (IPv4 first, IPv6 next) 63 | 10. Print the LISTEN files 64 | 65 | 66 | When the script has been modified, I (manually) move it to the deployment-server, OpenPortsURL 67 | (http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts), and create a `sha1`-file so that clients may 68 | get information about a new version being released. 69 | -------------------------------------------------------------------------------- /open_ports_install_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to install open_ports.sh on Linux 3 | # © Peter Möller, 2011-2012 4 | # open_ports.sh home page (english): 5 | # http://cs.lth.se/kontakt/peter_moller/script/open_portssh_en 6 | # open_ports.sh home page (swedish): 7 | # http://cs.lth.se/kontakt/peter_moller/script/open_portssh 8 | # 9 | # 2011-03-10 / Peter Möller, Datavetenskap, LTH 10 | # 2011-11-17: Fixed a bug that wiped out a previous crontab 11 | # 2011-11-30: Small fix 12 | # 2015-09-16: Moved to GitHub 13 | # Location: 14 | # http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports_install_linux.sh 15 | 16 | 17 | # Find out what OS is running. Quit if not Mac OS X or Linux 18 | OS="$(uname -s)" 19 | if [ ! "$OS" = "Darwin" -a ! "$OS" = "Linux" ]; then 20 | echo "Unknown Operating System!!! (according to \"uname -s\")" 21 | echo "This script only works on Mac OS X or Linux." 22 | echo "Exiting..." 23 | exit 1 24 | fi 25 | 26 | # Make sure the user is "root" 27 | if [ ! "$USER" = "root" ] ; then 28 | echo "Must be run by root!" 29 | echo "Exiting..." 30 | exit 1 31 | fi 32 | 33 | # Inform the user of what is going to happen 34 | printf "\e[1;4mInstallation of open_ports.sh:\e[0m\n" 35 | echo "This will install \"open_ports.sh\" on your computer." 36 | echo 37 | echo "The home page for the project is located here:" 38 | echo "http://cs.lth.se/kontakt/peter_moller/script/open_portssh_en" 39 | echo "There you will find more information about the script and also how to remove it." 40 | echo 41 | echo "Now the script will be downloaded and installed:" 42 | 43 | # Check to see if "curl" exists 44 | if [ -z "$(which -a curl 2>/dev/null)" ]; then 45 | echo "Warning: \"curl\" not found! Update of script will not work!" 46 | fi 47 | 48 | # make sure openssl exists 49 | if [ -z $(which openssl) ]; then 50 | echo "Warning: \"openssl\" not found! Checksum-verification will not work!" 51 | fi 52 | 53 | # BINDIR points to the "binary" 54 | BINDIR="/usr/bin" 55 | # PREFIX points to where all the datafiles are stored 56 | PREFIX="/usr/share/cs.lth.se/OpenPorts" 57 | # IP_CACHE is a growing list of IP-addresses and their geo location. 58 | # Since this is being used by other scripts, it's not in the OpenPorts directory 59 | IP_CACHE="/usr/share/cs.lth.se/ip_cache.txt" 60 | # GeoLookupDir is a dir where the geo lookup is stored 61 | GeoLookupDir="/usr/share/cs.lth.se/GeoLookup" 62 | # EXTERN stores the computers "external" address. Checked hourly 63 | EXTERN="$PREFIX/ExternIP.txt" 64 | # FILE4 stores current IPv4-ESTABLISHED connections. Generated every two minutes! 65 | FILE4="$PREFIX/ip4.txt" 66 | # FILE6 stores current IPv6-ESTABLISHED connections. Generated every two minutes! 67 | FILE6="$PREFIX/ip6.txt" 68 | # FILE_LISTEN stores current LISTEN connections. Generated every two minutes! 69 | FILE_LISTEN="$PREFIX/listen.txt" 70 | # CHECKSUM stores a sha1-checksum for the lsof-binary. Cheched every two houres 71 | CHECKSUM="$PREFIX/Checksum.txt" 72 | # IP_LOCATE_CACHE is a temporary file that stores the geo location of the computers external address 73 | IP_LOCATE_CACHE="$PREFIX"/ip_locate_cache.txt 74 | # OP_LOGG is a log file where all things related to open_ports.sh (install and upgrades) are noted 75 | OP_LOGG="$PREFIX"/OpenPorts_log.txt 76 | 77 | 78 | 79 | # fetch the open_ports-script 80 | printf "1. Fetching the main script (installs in \"$BINDIR\")..." 81 | #curl -o $BINDIR/open_ports.sh http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports.sh 2>/dev/null 82 | curl -o /tmp/open_ports.sh http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports.sh 2>/dev/null 83 | curl -o /tmp/open_ports.sh.sha1 http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports.sh.sha1 2>/dev/null 84 | if [ "$(openssl sha1 /tmp/${ScriptName} | awk '{ print $2 }')" = "$(less /tmp/${ScriptName}.sha1)" ]; then 85 | mv /tmp/open_ports.sh /usr/bin/open_ports.sh 86 | chmod 755 $BINDIR/open_ports.sh 87 | else 88 | echo "Checksum does NOT match!! Installation aborted!" 89 | exit 1 90 | fi 91 | 92 | # Countries.txt 93 | curl -o /tmp/Countries.txt http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/Countries.txt 2>/dev/null 94 | curl -o /tmp/Countries.txt.sha1 http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/Countries.txt.sha1 2>/dev/null 95 | if [ "$(openssl sha1 /tmp/Countries.txt | awk '{ print $2 }')" = "$(less /tmp/Countries.txt.sha1)" ]; then 96 | mv /tmp/Countries.txt ${PREFIX}/Countries.txt 97 | rm /tmp/Countries.txt.sha1 2>/dev/null 98 | fi 99 | printf " done!\n" 100 | 101 | # Fix cron 102 | command -v systemctl >/dev/null 2>&1 103 | if [ $? -eq 0 ]; then 104 | printf "2. Adding systemd unit to run the script every two minutes.\n" 105 | cp /home/pmoreau/softwares/open-ports/open-ports.timer /etc/systemd/system/ 106 | cp /home/pmoreau/softwares/open-ports/open-ports.service /etc/systemd/system/ 107 | systemctl enable open-ports.timer 108 | systemctl start open-ports.timer 109 | else 110 | command -v crontab >/dev/null 2>&1 111 | if [ $? -eq 0]; then 112 | printf "2. Fixing crontab for root (crontab runs the script every two minutes.\n" 113 | printf " This will NOT mess up previous crontab entries)..." 114 | crontab -l | grep -v "open_ports.sh" > /tmp/CRONFILE 115 | echo "*/2 * * * * $BINDIR/open_ports.sh" >> /tmp/CRONFILE 116 | crontab < /tmp/CRONFILE 117 | rm /tmp/CRONFILE 118 | printf " done!\n" 119 | else 120 | echo "systemd nor cron found on your computer: open-ports data won't be updated automatically" 121 | fi 122 | fi 123 | 124 | 125 | # Create the directory for the files and set the access rights 126 | printf "3. Creating the data-directories (located in \"$PREFIX\")..." 127 | mkdir -p "$PREFIX" 128 | chmod 755 "$PREFIX" 129 | mkdir "$GeoLookupDir" 130 | chmod 777 "$GeoLookupDir" 131 | #touch "$FILE4" "$FILE6" "$IP_CACHE" "$IP_LOCATE_CACHE" 132 | #chmod 666 "$FILE4" "$FILE6" "$IP_CACHE" "$IP_LOCATE_CACHE" 133 | touch "$FILE4" "$FILE6" 134 | chmod 666 "$FILE4" "$FILE6" 135 | printf " done!\n" 136 | 137 | echo 138 | printf "\e[1;4mDone!\e[0m\n" 139 | echo "\"open_ports.sh\" is now running and collect information every two minutes." 140 | echo "Run the script as an ordinary user to see the data." 141 | echo 142 | echo "In order for the geographical lookup to work, you need to get a [free] key from \"http://db-ip.com/api/\"." 143 | echo "Once you've gotten that key in your email, you need to store it as \"apidb.key\" in \"$PREFIX\"" 144 | echo "Opening this address in a few seconds..." 145 | /bin/sleep 5 146 | xdg-open "http://db-ip.com/api/free" & 147 | echo 148 | echo "Please do not forget to upgrade the script once every month or so! (\"open_ports.sh -u\")" 149 | echo "Also, please feel free to report bugs and email suggestions for improvements!" 150 | echo "Thank you!" 151 | echo "Peter Möller, Department of Computer Science, Lund University, Lund, Sweden" 152 | 153 | # Make an entry into the log book 154 | echo "$(date): \"open_ports.sh\" installed" >> "$OP_LOGG" 155 | 156 | exit 0 157 | -------------------------------------------------------------------------------- /open_ports_install_os_x.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to install open_ports.sh 3 | # © Peter Möller, 2011-2012 4 | # 2011-05-05 / Peter Möller, Datavetenskap, LTH 5 | # 2011-11-17: Fixed check of OS X version to determine which GeekTool to use 6 | # 2011-12-06: Added printout during installation 7 | # 2014-03-02: Changed to accomodated 8 | # 2015-09-16: Moved to GitHub 9 | # Location: 10 | # http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/open_ports_install.sh 11 | 12 | 13 | # Make sure the user is "root" 14 | if [ ! "$USER" = "root" ] ; then 15 | echo "Must be run by root!" 16 | echo "Exiting..." 17 | exit 1 18 | fi 19 | 20 | # ScriptName is the name of the script 21 | ScriptName="open_ports.sh" 22 | 23 | # Determine what OS is running and warn if not 10.6 or 10.7: 24 | SW_VERS="$(sw_vers -productVersion | cut -d\. -f2)" 25 | if [ -z "$(echo "6789" | grep -o $SW_VERS)" ]; then 26 | echo "\"$ScriptName\" has not been tried with Mac OS X 10.$SW_VERS!!" 27 | echo "It may not work." 28 | fi 29 | 30 | 31 | # BINDIR points to the "binary" 32 | BINDIR="/usr/local/bin" 33 | # PREFIX points to where all the datafiles are stored 34 | PREFIX="/Library/cs.lth.se/OpenPorts" 35 | ## IP_CACHE is a growing list of IP-addresses and their geo location. 36 | ## Since this is being used by other scripts, it's not in the OpenPorts directory 37 | #IP_CACHE="/Library/cs.lth.se/ip_cache.txt" 38 | # GeoLookupDir is a dir where the geo lookup is stored 39 | GeoLookupDir="/Library/cs.lth.se/GeoLookup" 40 | # EXTERN stores the computers "external" address. Checked hourly 41 | EXTERN="$PREFIX/ExternIP.txt" 42 | # FILE4 stores current IPv4-ESTABLISHED connections. Generated every two minutes! 43 | FILE4="$PREFIX/ip4.txt" 44 | # FILE6 stores current IPv6-ESTABLISHED connections. Generated every two minutes! 45 | FILE6="$PREFIX/ip6.txt" 46 | # FILE_LISTEN stores current LISTEN connections. Generated every two minutes! 47 | FILE_LISTEN="$PREFIX/listen.txt" 48 | # CHECKSUM stores a sha1-checksum for the lsof-binary. Cheched every two houres 49 | CHECKSUM="$PREFIX/Checksum.txt" 50 | ## IP_LOCATE_CACHE is a temporary file that stores the geo location of the computers external address 51 | #IP_LOCATE_CACHE="$PREFIX"/ip_locate_cache.txt 52 | # OP_LOGG is a log file where all things related to open_ports.sh (install and upgrades) are noted 53 | OP_LOGG="$PREFIX"/OpenPorts_log.txt 54 | 55 | # Inform the user of what is going to happen 56 | printf "\e[1;4mInstallation of \"$ScriptName\":\e[0m\n" 57 | echo "This will install \"$ScriptName\" on your computer." 58 | echo 59 | echo "The home page for the project is located here:" 60 | echo "http://cs.lth.se/kontakt/peter_moller/script/open_portssh_en" 61 | echo "There you will find more information about the script and also how to remove it." 62 | echo 63 | echo "Now the script will be downloaded and installed:" 64 | 65 | # Fetch and launch the launchd-component 66 | printf "1. Fetching the launchd-component (runs the script every two minutes)..." 67 | curl -o /Library/LaunchDaemons/se.lth.cs.open_ports.plist http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/se.lth.cs.open_ports.plist 2>/dev/null 68 | chmod 644 /Library/LaunchDaemons/se.lth.cs.open_ports.plist 69 | launchctl load /Library/LaunchDaemons/se.lth.cs.open_ports.plist 70 | launchctl start se.lth.cs.open_ports 71 | printf " done!\n" 72 | 73 | # Fetch the script 74 | printf "2. Fetching the main script and the country list..." 75 | # open_ports.sh 76 | curl -o /tmp/${ScriptName} http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/${ScriptName} 2>/dev/null 77 | curl -o /tmp/${ScriptName}.sha1 http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/${ScriptName}.sha1 2>/dev/null 78 | if [ "$(openssl sha1 /tmp/${ScriptName} | awk '{ print $2 }')" = "$(less /tmp/${ScriptName}.sha1)" ]; then 79 | mkdir -p /usr/local/bin 2>/dev/null 80 | mv /tmp/${ScriptName} ${BINDIR}/${ScriptName} 81 | chmod 755 ${BINDIR}/${ScriptName} 82 | else 83 | echo "Checksum does NOT match!! Installation aborted!" 84 | exit 1 85 | fi 86 | # Countries.txt 87 | curl -o /tmp/Countries.txt http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/Countries.txt 2>/dev/null 88 | curl -o /tmp/Countries.txt.sha1 http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/Countries.txt.sha1 2>/dev/null 89 | if [ "$(openssl sha1 /tmp/Countries.txt | awk '{ print $2 }')" = "$(less /tmp/Countries.txt.sha1)" ]; then 90 | mv /tmp/Countries.txt ${PREFIX}/Countries.txt 91 | rm /tmp/Countries.txt.sha1 2>/dev/null 92 | fi 93 | printf " done!\n" 94 | 95 | # Create the directory for the files and set the access rights 96 | printf "3. Creating the data-directories..." 97 | mkdir -p "$PREFIX" 98 | chmod 755 "$PREFIX" 99 | mkdir "$GeoLookupDir" 100 | chmod 777 "$GeoLookupDir" 101 | touch "$FILE4" "$FILE6" 102 | chmod 666 "$FILE4" "$FILE6" 103 | printf " done!\n" 104 | 105 | # Send a signal that someone has installed the script 106 | # This is only to give me feedback that someone is actually using this 107 | # I will *not* use the data in any way or give it away! 108 | curl -s -f -e "$ScriptName OS X 10.${SW_VERS}" -o /dev/null http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts/installed 2>/dev/null 109 | 110 | echo "Done installing base parts of \"$ScriptName\". Now proceeding to install GeekTool" 111 | echo "(GeekTool is not a part of \"$ScriptName\"; it is used to display the output of the script" 112 | echo "on the desktop of your computer. You may skip it if you like)." 113 | echo 114 | 115 | # Getting GeekTool 116 | if [ -z "$(ls /Library/PreferencePanes/GeekTool.prefPane 2>/dev/null)" -a -z "$(ls /Users/*/Library/PreferencePanes/GeekTool.prefPane 2>/dev/null)" -a -z "$(ls /Applications/GeekTool.app 2>/dev/null)" ]; then 117 | if [ "$SW_VERS" = "6" ]; then 118 | echo "Fetching GeekTool for Snow Leopard" 119 | # Get GeekTook 120 | curl -o /tmp/GeekTool.dmg http://update.tynsoe.org/geektool3/Public/GeekTool%203.0.dmg 2>/dev/null 121 | hdiutil mount /tmp/GeekTool.dmg 122 | open /Volumes/GeekTool\ 3/ 123 | echo "GeekTool has been downloaded, but you must install it yourself!" 124 | elif [ "$SW_VERS" = "7" -o "$SW_VERS" = "8" -o "$SW_VERS" = "9" -o "$SW_VERS" = "10" -o "$SW_VERS" = "11" ]; then 125 | echo "GeekTool is available from this address:" 126 | echo "http://projects.tynsoe.org/en/geektool/download.php" 127 | echo "Opening this address in a few seconds..." 128 | /bin/sleep 5 129 | open "http://projects.tynsoe.org/en/geektool/download.php" & 130 | else 131 | echo "Sorry: you are running a version of Mac OS X that will not work with GeekTool." 132 | echo "You will have to find a version for yourself..." 133 | fi 134 | else 135 | echo "It looks as if you already have GeekTool installed." 136 | fi 137 | 138 | echo 139 | printf "\e[1;4mDone!\e[0m\n" 140 | echo "\"$ScriptName\" is now running and collect information every two minutes." 141 | echo "Run the script as an ordinary user to see the data." 142 | echo 143 | printf "\e[1;3mLocations:\e[0m\n" 144 | echo "The script is located in \"${BINDIR}\"" 145 | echo "The data files are stored in \"$PREFIX\"" 146 | echo "The launchd-file is \"/Library/LaunchDaemons/se.lth.cs.open_ports.plist\"" 147 | echo "These are the files you need to remove to uninstall!" 148 | echo 149 | echo "In order for the geographical lookup to work, you need to get a [free] key from \"http://db-ip.com/api/\"." 150 | echo "Once you've gotten that key in your email, you need to store it as \"apidb.key\" in \"$PREFIX\"" 151 | echo "Opening this address in a few seconds..." 152 | /bin/sleep 5 153 | open "http://db-ip.com/api/free" & 154 | echo 155 | echo "Please do not forget to upgrade the script once every month or so! (\"$ScriptName -u\")" 156 | echo "(I would suggest that you do this from \"root\"_s crontab)" 157 | echo 158 | echo "Also, please feel free to report bugs and email suggestions for improvements!" 159 | echo "Thank you!" 160 | echo "Peter Möller, Department of Computer Science, Lund University, Lund, Sweden" 161 | 162 | # Make an entry into the log book 163 | echo "$(date): \"open_ports.sh\" installed" >> "$OP_LOGG" 164 | exit 0 165 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /open_ports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Script to list open TCP-connections on Mac OS X 10.6, 10.7, 10.8, 10.9, 10.10 and 10.11 and Linux 4 | # The script came to life in 2011 5 | # 6 | # Copyright 2015 Peter Möller, Dept of Copmuter Science, Lund University 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | # 21 | # Script home page (english): 22 | # http://cs.lth.se/kontakt/peter_moller/script/open_portssh_en 23 | # Script home page (swedish): 24 | # http://cs.lth.se/kontakt/peter_moller/script/open_portssh 25 | # 2011-06-23 All comments translated to english (phew!) 26 | # 2011-07-13 Auto-update disabled! Instead, it notify the user of updates 27 | # Also feedback for when data is generated 28 | # Bug-fix from Roman Weber about IPv6-parsing (thanks!) 29 | # 2011-08-27 Changed URL of "whatismyip" 30 | # 2011-11-30 Polished 31 | # 2011-12-07 Version included in curl call 32 | # 2013-03-11 Disabled the use of geoiptool (sadly). Looking for a replacement 33 | # Also changed the external IP-address lookup 34 | # 2013-04-23 Fixed garbage in the $IP_CACHE-file 35 | # 2014-03-01 Implemented a new IP-lookup system using http://db-ip.com/ (Thank you, guys!) 36 | # 2015-09-16 Moved to GitHub (finally!) 37 | # 2021-01-26 Removed the update functionality. Everything now goes via git 38 | # 39 | # Version: 40 | VER="3.5" 41 | # 42 | # Note: The script is dependant on two external web-addresses: 43 | # 1. http://api.db-ip.com/addrinfo?addr=8.9.10.11&api_key=123456789123456789 44 | # Performs the mapping from IP address to Country and City 45 | # One must register by them and get a key (stored in $PREFIX/apidb.key) 46 | # Also, one must not perform more than 5.000 lookups per day 47 | # 2. http://tejji.com/ip/my-ip-address.aspx 48 | # Finds out the external IP-address you have if you are behind a NAT-router 49 | # 50 | # Adaption to Linux (Mandriva) 51 | # Lines that start with "##" are “issues” from Mac OS X to Linux 52 | # 53 | # Things to fix: 54 | # • How to present it on the screen on Linux 55 | # • IPv6/ESTABLISHED! 56 | 57 | help() { 58 | echo 59 | echo "Usage: $0 [-u]" 60 | echo 61 | echo "-u: Update the script" 62 | echo 63 | echo "If run by root: datafiles in /Library/cs.lth.se/OpenPorts (Mac) or /usr/share/cs.lth.se/OpenPorts (Linux) are created, but no output." 64 | echo "If run by any other user: output is displayed based on those datafiles." 65 | echo 66 | if [ "$OS" = "Darwin" ]; then 67 | echo "This script is supposed to be used in conjunction with a launchd-component, se.lth.cs.open_ports," 68 | echo "that creates the datafiles in /Library/OpenPorts every two minutes. The use of GeekTool to display the result" 69 | echo "is also part of the idea behind this script!" 70 | elif [ "$OS" = "Linux" ]; then 71 | echo "This script is supposed to be used in conjunction with a cron job or a systemd timer that creates the" 72 | echo "datafiles in /usr/share/cs.lth.se/OpenPorts every two minutes. Conky can be used to display the result" 73 | echo "of this script!" 74 | fi 75 | exit 0 76 | } 77 | 78 | # Locate an IP-address. Gives: 79 | # Country: Country 80 | # City: City 81 | # to std. out 82 | # 2014-03-01: OBSOLETE!! Only here for reference 83 | locate_ip() { 84 | curl http://www.geoiptool.com/en/?IP=$1 2>/dev/null | awk ' 85 | /(Country:|City)/ { 86 | record="t";gsub("[\t ]*<[^>]*>",""); printf("%-1s ",$0);next; 87 | } 88 | record == "t" { gsub("[\t ]*<[^>]*>[\t ]*","");print $0;record="f";next} 89 | {next} 90 | END{print ""}' 91 | } 92 | 93 | 94 | # Do the Geo Lookup (if key exists) 95 | # Assumes: 96 | # - $1: IP 97 | # curl 'http://api.db-ip.com/addrinfo?addr=68.169.130.16&api_key=123456789123456789' 98 | # Gives: 99 | # - a file, $GeoLookupDir/$IP_to_check, containing "Country Name:City Name" 100 | function PerformGeoLookup () 101 | { 102 | if [ -n "$GeoLookupKey" ]; then 103 | IP_to_check="$1" 104 | if [ -z "$(echo $IP_to_check | sed 's/[0-9\.]//g')" ]; then 105 | Rad="$(curl -s "$GeoLookupURL$IP_to_check&api_key=$GeoLookupKey")" 106 | [ "$debug" = "t" ] && echo "$(date +%F" "%T); #99; $$; User=\"$USER\"; PerformGeoLookup, IP_to_check=\"$IP_to_check\", Rad=\"$Rad\"" >> $IP_loggfile 107 | # -> Rad='{"address":"78.69.30.61","country":"SE","stateprov":"Stockholm County","city":"Farsta"}' 108 | # Simple sanity check: count the number of qoutation marks (should be 16) 109 | if [ "$(echo $Rad | grep -o '"' | wc -w | awk '{print $1}')" -eq 16 ]; then 110 | City="$(echo $Rad | cut -d\" -f 16)" 111 | Country="$(grep "$(echo $Rad | cut -d\" -f 8)" $CountryList | cut -d: -f2)" 112 | else 113 | City="???" 114 | Country="???" 115 | fi 116 | # Write to file 117 | echo "$City:$Country" > "$GeoLookupDir/${IP_to_check}.txt" 118 | [ "$debug" = "t" ] && echo "$(date +%F" "%T); #95; $$; User=\"$USER\"; PerformGeoLookup (IP=\"$IP\", IP_to_check=\"$IP_to_check\", City=\"$City\", Country=\"$Country\")" >> $IP_loggfile 119 | else 120 | City="???" 121 | Country="???" 122 | fi 123 | fi 124 | } 125 | 126 | 127 | # Check to see if $IP already exist in $GeoLookupDir and get $Country and $City 128 | # Otherwise, find the information and update $IP_CACHE 129 | # Assume: 130 | # - IP 131 | # Gives: $Country & $City and eventually a new entry in $GeoLookupDir 132 | function GetCityCountry() 133 | { 134 | # (DIRT REMOVED) DIRTY fix for IPv6. Will need to work on this!! 135 | #if [ -n "$(echo $IP | sed 's/[0-9.]//g')" ]; then 136 | # IP="$(echo $IP | cut -d: -f1)" 137 | #fi 138 | if [ -r "$GeoLookupDir/${IP}.txt" ]; then 139 | #City="$(less "$GeoLookupDir/${IP}.txt" | cut -d: -f1 | native2ascii -encoding UTF-8 -reverse)" 140 | City="$(less "$GeoLookupDir/${IP}.txt" | cut -d: -f1)" 141 | Country="$(less "$GeoLookupDir/${IP}.txt" | cut -d: -f2)" 142 | # FUTURE FEATURE: INCREASE COUNTER 143 | [ "$debug" = "t" ] && echo "$(date +%F" "%T); #135; $$; User=\"$USER\"; GetCityCountry ($IP, City=\"$City\", Country=\"$Country\")" >> $IP_loggfile 144 | else 145 | PerformGeoLookup $IP 146 | fi 147 | } 148 | 149 | # Clean the GeoLocate-cache and remove entries older than 4 weeks 150 | function CleanGeoLocate() 151 | { 152 | find "$GeoLookupDir" -type f -mtime +4w -exec rm -f {} \; 2>/dev/null 153 | } 154 | 155 | 156 | # Get DNS for $IP 157 | # Gives: $HOSTNAME 158 | # Will also deal with the private addresses: 159 | # • 10.x.x.x 160 | # • 172.16.x.x 161 | # • 192.168.x.x 162 | # as well as self-assigned address: 163 | # 169.254.x.x 164 | function GetDNS() 165 | { 166 | PrivateAddress="No" 167 | if [ -z "${IP/127.0.0.1}" ]; then 168 | HOSTNAME="localhost" 169 | elif [ "$(echo "$IP" | cut -d\. -f1)" = "10" ]; then 170 | HOSTNAME="Private address ($IP)" 171 | PrivateAddress="Yes" 172 | elif [ "$(echo "$IP" | cut -d\. -f1,2)" = "172.16" ]; then 173 | HOSTNAME="Private address ($IP)" 174 | PrivateAddress="Yes" 175 | elif [ "$(echo "$IP" | cut -d\. -f1,2)" = "192.168" ]; then 176 | HOSTNAME="Private address ($IP)" 177 | PrivateAddress="Yes" 178 | elif [ "$(echo "$IP" | cut -d\. -f1,2)" = "169.254" ]; then 179 | HOSTNAME="Self-assigned address ($IP)" 180 | PrivateAddress="Yes" 181 | else 182 | HOSTNAME_tmp="$(host -W 2 $IP)" 183 | ERR="$?" 184 | if [ ! "$ERR" = "0" ]; then 185 | HOSTNAME="$IP (DNS timeout)" 186 | # HOSTNAME="$IP could not be looked up! (DNS timeout)" 187 | else 188 | HOSTNAME=`echo $HOSTNAME_tmp | awk '{ print $NF }' | sed 's/\.$//g'` 189 | fi 190 | fi 191 | } 192 | 193 | 194 | # Quit if there already is a running “open_ports.sh” 195 | # Typical line: 196 | # 501 7307 7301 0 9:53am ttys001 0:00.02 /bin/bash /usr/bin/open_ports.sh 197 | if [ "$(ps -ef | grep "^\ *${UID}\ .*/[b]ash\ .*/[o]pen_ports.sh$" | wc -l)" -gt "2" ]; then 198 | echo "\"open_ports.sh\" already running -- will exit now" 199 | exit 0 200 | fi 201 | 202 | # Find the OS. Quit if it's not either Mac OS X or Linux 203 | OS="$(uname -s)" 204 | if [ ! "$OS" = "Darwin" -a ! "$OS" = "Linux" ]; then 205 | echo "Unknown Operating System!!!" 206 | echo "This script only works on Mac OS X or Linux." 207 | echo "Exiting..." 208 | exit 1 209 | fi 210 | 211 | # If it is Linux, figure out whether to use systemd or crontab 212 | TIMER_METHOD="none" 213 | if [ "$OS" = "Darwin" ]; then 214 | TIMER_METHOD="launchd" 215 | elif [ "$OS" = "Linux" ]; then 216 | command -v systemctl >/dev/null 2>&1 217 | if [ $? -eq 0 ]; then 218 | TIMER_METHOD="systemd" 219 | else 220 | command -v crontab >/dev/null 2>&1 221 | if [ $? -eq 0 ]; then 222 | TIMER_METHOD="cron" 223 | fi 224 | fi 225 | fi 226 | 227 | # Read the parameters: 228 | while getopts ":hud" opt; do 229 | case $opt in 230 | u ) fetch_new=t;; 231 | d ) debug=t;; 232 | \?|h ) help;; 233 | esac 234 | done 235 | 236 | 237 | # Get, and print, IP-addresses for all active interfaces based on $NetworkInterfaces 238 | # This is, as yet, Mac-only 239 | function PrintAllInterfaces() 240 | { 241 | #NSOfile="/tmp/NetworkServiceOrder_$$.txt" 242 | #networksetup -listnetworkserviceorder | grep -A 1 "^([0-9])\ " | grep "[a-z][0-9])$" | cut -d: -f2,3 | sed -e 's/, Device//g' -e 's/)//g' -e 's/^ //g' > $NSOfile 243 | NSO="$(networksetup -listnetworkserviceorder | grep -A 1 "^([0-9])\ " | grep "[a-z][0-9])$" | cut -d: -f2,3 | sed -e 's/, Device//g' -e 's/)//g' -e 's/^ //g')" 244 | #NetworkInterfaces="$(less $NSOfile | cut -d: -f2)" 245 | NetworkInterfaces="$(echo "$NSO" | cut -d: -f2)" 246 | # Ex: NetworkInterfaces=' en0 en1 en5 en2 bridge0' 247 | #echo "Available network interfaces: $NetworkInterfaces" 248 | FormatStringInterfaces="%-25s%-5s%-17s%-26s" 249 | # Thunderbolt Ethernet en1 130.235.120.242 fe80::1610:9fff:fece:fd95 250 | # 1234567890123456789012345678901234567890123456789012345678901234567890 251 | # 1 2 3 4 5 6 7 252 | 253 | NumActiveInterfaces="$(ifconfig | grep ":\ active$" | wc -l | awk '{print $1}')" 254 | 255 | # Print information about the various interfaces if there are more than one interface 256 | if [ $NumActiveInterfaces -gt 1 ]; then 257 | echo 258 | printf "${ESC}${BlackBack};${WhiteFont}mActive interfaces, in service order:${Reset}\n" 259 | IfNum=1 260 | for j in $NetworkInterfaces 261 | do 262 | IF="$(ifconfig $j 2>/dev/null | egrep "inet[6]?\ |status:\ ")" 263 | # Ex: IF='inet6 fe80::217:f2ff:fe04:4229%en1 prefixlen 64 scopeid 0x5 inet 192.168.1.69 netmask 0xffffff00 broadcast 192.168.1.255 status: active' 264 | if [ $? -eq 0 ]; then 265 | Active="$(echo $IF | egrep -o "status: [a-z0-9][^\ ]*" | awk '{print $2}')" 266 | if [ -z "${Active/active/}" ]; then 267 | IFName="$(echo "$NSO" | grep $j | cut -d: -f1)" 268 | # Ex: IFName='Ethernet 2' 269 | I4="$IFName ($j): $(echo $IF | egrep -o "inet\ [a-z0-9][^\ ]*" | awk '{print $2}')" # Ex: I4='Ethernet 2 (en1): 192.168.1.69' 270 | IP4_addr="$(echo $IF | egrep -o "inet\ [a-z0-9][^\ ]*" | awk '{print $2}')" # Ex: IP4_addr='192.168.50.201' 271 | #I6="$IFName ($j): $(echo $IF | egrep -o "inet6\ [a-z0-9][^\ ]*" | awk '{print $2}' | egrep -o "[^%]*")" 272 | I6="$IFName ($j): $(echo "$IF" | grep -Eo "^\s*inet6\ [a-z0-9:]*[^%]" | awk '{print $2}')" # Ex: I6='Wi-Fi (en0): fe80::ced:c35a:6cbe:6ab1' 273 | IP6_addr="$(echo "$IF" | grep -Eo "^\s*inet6\ [a-z0-9:]*[^%]" | awk '{print $2}')" # Ex: IP6_addr='fe80::ced:c35a:6cbe:6ab1' 274 | printf "${ESC}${WhiteBack};${BlackFont}m${FormatStringInterfaces}${Reset}\n" "${IfNum}. ${IFName}" "$j" "$IP4_addr" "$IP6_addr" 275 | let IfNum=( $IfNum + 1 ) 276 | fi 277 | fi 278 | done 279 | fi 280 | # Clean up the $NSOfile 281 | #/bin/rm "$NSOfile" 2>/dev/null 282 | } 283 | 284 | 285 | # Basic settings: 286 | # PREFIX points to where the data files are stored. 287 | # IP_CACHE is a growing list of IP-addresses and their geographical location. 288 | # Since this is used by other scripts, it is not located in the OpenPorts directory 289 | if [ "$OS" = "Darwin" ]; then 290 | PREFIX="/Library/cs.lth.se/OpenPorts" 291 | IP_CACHE="/Library/cs.lth.se/ip_cache.txt" 292 | # GeoLookupDir is a dir where the geo lookup is stored 293 | GeoLookupDir="/Library/cs.lth.se/GeoLookup" 294 | #DEFAULT_INTERFACE="$(route get www.lu.se | grep interface | awk '{ print $2 }')" 295 | DEFAULT_INTERFACE="$(/usr/sbin/netstat -f inet -rn | grep "^default" | head -1 | awk '{print $NF}')" 296 | MY_IP_ADDRESS="$(ifconfig $DEFAULT_INTERFACE 2>/dev/null | grep "inet " | awk '{ print $2 }')" 297 | #DOMAIN="`ipconfig getpacket en0 | grep 'domain_name (string)' | awk '{ print $3 }'`" 298 | DOMAIN="$(hostname | cut -d\. -f2-7)" 299 | MTIME60m="-mtime -60m" 300 | MTIME120m="-mtime -120m" 301 | MTIME7d="-mtime -7d" 302 | elif [ "$OS" = "Linux" ]; then 303 | PREFIX="/usr/share/cs.lth.se/OpenPorts" 304 | IP_CACHE="/usr/share/cs.lth.se/ip_cache.txt" 305 | # GeoLookup is a dir where the geo lookup is stored 306 | GeoLookupDir="/usr/share/cs.lth.se/GeoLookup" 307 | DEFAULT_INTERFACE="$(/sbin/route | grep "^default" | awk '{ print $NF }')" 308 | MY_IP_ADDRESS="$(/sbin/ifconfig $DEFAULT_INTERFACE | grep "inet " | awk '{ print $2 }' | cut -d: -f2)" 309 | DOMAIN="$(dig +search +short -x $MY_IP_ADDRESS | cut -d\. -f2-8 | sed 's/\.$//g')" 310 | MTIME60m="-mmin -60" 311 | MTIME120m="-mmin +120" 312 | MTIME7d="-mtime -7" 313 | fi 314 | # BINDIR is where open_ports.sh should be 315 | BINDIR="/usr/local/bin" 316 | # OpenPortURL is where open_ports.sh and Countries.txt resides 317 | OpenPortsURL="http://fileadmin.cs.lth.se/cs/Personal/Peter_Moller/scripts" 318 | # NAT has content if we are on a private net (^192.168.|^172.16.|^10.) and empty otherwise 319 | NAT="$(echo $MY_IP_ADDRESS | egrep "^192.168.|^172.16.|^10.")" 320 | # ScriptName is simply the name of the script... 321 | ScriptName="$(basename $0)" 322 | # EXTERN stores the computers “external” address. It is checked hourly 323 | EXTERN="$PREFIX"/ExternIP.txt 324 | # ExternHistory stores a history of your external IP-addresses 325 | ExternHistory="$PREFIX"/ExternIP_history.txt 326 | # GeoLookupURL is where the Geo Lookup is performed 327 | GeoLookupURL="http://api.db-ip.com/addrinfo?addr=" 328 | # GeoLookupKey is the key that is nessecary to actually perform geolookup 329 | GeoLookupKey="$(cat $PREFIX/apidb.key 2>/dev/null)" 330 | # FILE4 stores currently IPv4-ESTABLISHED connections. Generated every 2 minutes 331 | FILE4="$PREFIX"/ip4.txt 332 | # FILE6 stores currently IPv6-ESTABLISHED connections. Generated every 2 minutes 333 | FILE6="$PREFIX"/ip6.txt 334 | # FILE_LISTEN stores current LISTEN-connections. Generated every 2 minutes 335 | FILE_LISTEN="$PREFIX"/listen.txt 336 | # IP_LOCATE_CACHE is a temporary file that stores the geo location of the external address 337 | IP_LOCATE_CACHE="$PREFIX"/ip_locate_cache.txt 338 | # Empty file whose existence signals that the launchd-part of open_ports is NOT running 339 | LAUNCHD_FLAG="$PREFIX"/no_launchd 340 | # SoftwareUpdate-fil (temporary) 341 | SoftUpd=/tmp/swu.temp 342 | # String for printf (used to print ESTABLISHED-connections) 343 | Formatstring1="%-24s%-14s%-15s%2s%3s%-58s%-20s%-14s" 344 | Formatstring2="%-24s%-14s%-15s%2s%3s%-58s" 345 | # String for printf (used to print LISTEN-ports) 346 | FormatstringListen="%-6s%-6s%-18s%-15s%6s%2s%-17s%-15s" 347 | # UpdateMessage contains the message of weather an update is available och the checksum-check failed 348 | UpdateMessage="" 349 | # OP_LOGG is a log file where all things related to open_ports.sh (install and upgrades) are noted 350 | OP_LOGG="$PREFIX"/OpenPorts_log.txt 351 | # $CountryList is a list (stored locally, comes from http://www.worldatlas.com/aatlas/ctycodes.htm) of all the countries in the world 352 | CountryList="$PREFIX/Countries.txt" 353 | # IP_loggfile is used for debugging. It contains one line per IP lookup, along with PID and time stamp 354 | IP_loggfile=$PREFIX/IP_loggfil.txt 355 | 356 | 357 | 358 | # (Colors can be found at http://en.wikipedia.org/wiki/ANSI_escape_code, http://graphcomp.com/info/specs/ansi_col.html and other sites) 359 | Reset="\e[0m" 360 | ESC="\e[" 361 | RES="0" 362 | BoldFace="1" 363 | ItalicFace="3" 364 | UnderlineFace="4" 365 | SlowBlink="5" 366 | BlackBack="40" 367 | RedBack="41" 368 | YellowBack="43" 369 | BlueBack="44" 370 | WhiteBack="47" 371 | BlackFont="30" 372 | RedFont="31" 373 | GreenFont="32" 374 | YellowFont="33" 375 | BlueFont="34" 376 | CyanFont="36" 377 | WhiteFont="37" 378 | 379 | # Reset all colors 380 | BGColor="$RES" 381 | Face="$RES" 382 | FontColor="$RES" 383 | 384 | # Create LSOF_PATH 385 | if [ -x /usr/sbin/lsof ]; then 386 | LSOF_PATH="/usr/sbin" 387 | elif [ -x /usr/bin/lsof ]; then 388 | LSOF_PATH="/usr/bin" 389 | fi 390 | 391 | 392 | # ================================================================================================================= 393 | # ================================================================================================================= 394 | # ================================ D A T A I S G E N E R A T E D H E R E ================================== 395 | # ================================================================================================================= 396 | # ================================================================================================================= 397 | # 398 | # Create in-data (if run through launchd, $USER = nil or root) and then stop 399 | # 400 | if [ "$USER" = "root" -o -z "$USER" ]; then 401 | if [ -z "$DEFAULT_INTERFACE" ] ; then 402 | echo "You have no IP-address. Exiting" 403 | exit 1 404 | fi 405 | 406 | 407 | printf "Generating datafiles..." 408 | 409 | # Check that the base files exist (otherwise create them and set access rights) 410 | # (need to use cut to not see extended attributes that will mess up the test) 411 | if [ ! "$(ls -ls "$FILE4" 2> /dev/null | awk '{ print $2 }' | cut -c1-10)" = "-rw-rw-rw-" ]; then 412 | mkdir -p $(dirname "$FILE4") 2> /dev/null 413 | [[ "$OS" = "Darwin" ]] && chgrp -R staff `dirname "$FILE4"` 414 | chmod 775 $(dirname "$FILE4") 415 | touch "$FILE4" "$FILE6" "$IP_CACHE" "$IP_LOCATE_CACHE" "$EXTERN" "$FILE_LISTEN" 416 | #chmod 666 `dirname "$FILE4"`/??* 417 | fi 418 | 419 | # Check the external IP-adress: 420 | # A) has it been updated recently (≤ 60 minutes) 421 | # B) is it a reasonably address 422 | # C) does it differ from the previously stored $EXTERN 423 | # D) if so, remove 127.0.0.1 from $GeoLookupDir (since it's not correct) 424 | if [ -z "$(find $EXTERN -type f ${MTIME60m} 2> /dev/null)" ]; then 425 | #echo "$(curl http://tejji.com/ip/my-ip-address.aspx 2> /dev/null | grep -A 1 '
' | tail -1 | sed -E 's/<[/]?span[^>]*>//g' | awk '{print $1}')" > /tmp/slaskextern 426 | #SlaskExtern="$(curl http://tejji.com/ip/my-ip-address.aspx 2> /dev/null | grep -A 1 '
' | tail -1 | sed -E 's/<[/]?span[^>]*>//g' | awk '{print $1}' | tr -d '\r\n')" 427 | # SlaskExtern replaced with simplier call thanks to great feedback from a User op open_ports! :-) I keep the old function for future reference. 428 | SlaskExtern="$(curl http://ipecho.net/plain 2> /dev/null)" 429 | [ "$debug" = "t" ] && echo "$(date +%F" "%T); #479; $$; User=\"$USER\"; curl to ipecho.net for external address" >> $IP_loggfile 430 | # Check to see if this is an IP-address (it should be an empty string after sed if it is) 431 | if [ -z "$(echo $SlaskExtern | sed 's/[0-9\.]//g')" ]; then 432 | # If it's different from the stored one; we have moved and need to update $EXTERN 433 | # and store the external address along with a timestamp in $ExternHistory 434 | if [ ! "$SlaskExtern" = "$(less $EXTERN 2>/dev/null)" ]; then 435 | IP="$SlaskExtern" 436 | if [ -r "${GeoLookupDir}/${IP}.txt" ]; then 437 | GetCityCountry $IP 438 | else 439 | PerformGeoLookup $IP 440 | fi 441 | # echo "Add to history file" 442 | echo "$IP:$Country:$City:`date +%Y-%m-%d,\ %H.%M`" >> "$ExternHistory" 443 | echo "$SlaskExtern" > "$EXTERN" 444 | # Also, create a new file for 127.0.0.1 (since it will be a new one) 445 | PerformGeoLookup "$(less $EXTERN)" 446 | echo "$City:$Country" > "${GeoLookupDir}/127.0.0.1.txt" 447 | # rm $"{GeoLookupDir}/127.0.0.1" 2>/dev/null 448 | else 449 | # Touch $EXTERN so it will not check the external address every 2 minutes 450 | touch "$EXTERN" 451 | fi 452 | fi 453 | fi 454 | 455 | 456 | # Create data for ESTABLISHED: 457 | # Previous capture line. Still here for reference: 458 | # lsof +c 0 -i 4 -n | grep EST | grep -v "\->127.0.0.1" | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed 's/\ [[:digit:]].*-\>/\ /g' | sed 's/:/\ /g' | sort -f | uniq -c > $FILE4 459 | if [ "$OS" = "Darwin" ]; then 460 | $LSOF_PATH/lsof +c 0 -i 4 -n | grep EST | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed 's/\ [[:digit:]].*-\>/\ /g' | sed 's/:/\ /g' | sort -f | uniq -c > $FILE4 461 | # “sanitize” the output by replacing long strings with shorter ones. This started in OS X 10.11 “El Capitan” 462 | # The following strings are inteded to be cought: 463 | # - 'com.apple.WebKit.*' 464 | # - 'com.apple.Safari.*' 465 | # - '2BUA8C4S2C.com.*' 466 | sed -e 's/com.apple.//' -e 's/2BUA8C4S2C.com[a-z.]* /1Password /' -i .bak $FILE4 467 | 468 | 469 | # The following line is replaced by the one next below after a bug report from Roman Weber. Have not had time to check i thoroughly, though, so it's still here: 470 | #$LSOF_PATH/lsof +c 0 -i 6 -n | grep EST | grep -v "\->\[\:\:$MY_IP_ADDRESS\]" | sort -f -k 1,1 -k 2,2 | awk '{ print $1" "$3" "$9 }' | sed -E "s/\ \[::[[:digit:]].*-\>\[::/\ /g" | sed "s/\]:/\ /g" | sort -f | uniq -c > $FILE6 471 | # Something is definetley not right here. Another fix and, I guess, primarily waiting for a couple of 'real' IPv6-catches... 472 | #$LSOF_PATH/lsof +c 0 -i 6 -n | grep EST | grep -v "\->\[\:\:$MY_IP_ADDRESS\]" | sort -f -k 1,1 -k 2,2 | awk '{ print $1" "$3" "$9 }' | sed -E "s/\ \[.*-\>\[/\ /g" | sed "s/\]:/\ /g" | sort -f | uniq -c > $FILE6 473 | # $LSOF_PATH/lsof +c 0 -i 6 -n | grep EST | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed 's/\ [[:digit:]].*-\>/\ /g' | sed 's/:/\ /g' | sort -f | uniq -c > $FILE6 474 | $LSOF_PATH/lsof +c 0 -i 6 -n | grep EST | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed -e 's/ \[[^-]*->/ /g' -e 's/]:/] /g' | sort -f | uniq -c > $FILE6 475 | elif [ "$OS" = "Linux" ]; then 476 | $LSOF_PATH/lsof +c 0 -i 4 -n | grep EST | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print $1" "$3" "$9 }' | sed 's/\ [[:digit:]].*->/\ /g' | sed 's/:/\ /g' | sort -f | uniq -c > $FILE4 477 | # Have not had access to a linux machine running IPv6 so for Linux we simply skip IPv6 for the time being 478 | ## $LSOF_PATH/lsof +c 0 -i 6 -n | grep EST | grep -v "->\[\:\:$MY_IP_ADDRESS\]" | sort -f -k 1,1 -k 2,2 | awk '{ print $1" "$3" "$9 }' | sed -E "s/\ \[::[[:digit:]].*->\[::/\ /g" | sed "s/\]:/\ /g" | sort -f | uniq -c > $FILE6 479 | fi 480 | # For future development: the ip6-lines to be grep'ed *should* look like this: 481 | # lsof -n -i 6 | grep EST 482 | # Screen 56128 peterm 6u IPv6 0x169caf80 0t0 TCP [fde2:ccd9:7a6b:7089:21e:52ff:fe83:b033]:51199->[fd58:97aa:2e6:277d:217:f2ff:fe04:4228]:vnc-server (ESTABLISHED) 483 | # (captured ARD-session home) 484 | # This is how it looks in the other end: 485 | # AppleVNCS 56767 peterm 11u IPv6 0x09646d10 0t0 TCP [fd58:97aa:2e6:277d:217:f2ff:fe04:4228]:vnc-server->[fde2:ccd9:7a6b:7089:21e:52ff:fe83:b033]:51199 (ESTABLISHED) 486 | 487 | 488 | # Create data for LISTEN: 489 | if [ "$OS" = "Darwin" ]; then 490 | $LSOF_PATH/lsof +c 0 -i 4 -n | grep LISTEN | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print "4 - "$1" "$3" "$9 }' | sed 's/:/\ /g' | sed 's/\ [[:digit:]]\{2,5\}$/\ anonymous_port/g' | uniq > /tmp/slask 491 | $LSOF_PATH/lsof +c 0 -i 6 -n | egrep LISTEN | awk '{ print "- 6 "$1" "$3" "$9 }' | sort -f | sed 's/\ \[.*\]/\ \*/g' | sed 's/:/\ /g' | sed 's/\ [[:digit:]]\{2,5\}$/\ anonymous_port/g' | uniq >> /tmp/slask 492 | # Clean '1Password' 493 | sed -e 's/2BUA8C4S2C.com[a-z.]* /1Password /' -i .bak /tmp/slask 494 | elif [ "$OS" = "Linux" ]; then 495 | $LSOF_PATH/lsof +c 0 -i 4 -n | grep LISTEN | sort -f -k 1,1 | cut -d\( -f1 | awk '{ print "4 - "$1" "$3" "$9 }' | sed 's/:/\ /g' | sed 's/\ [[:digit:]]\{2,5\}$/\ anonymous_port/g' | uniq > /tmp/slask 496 | $LSOF_PATH/lsof +c 0 -i 6 -n | egrep LISTEN | awk '{ print "- 6 "$1" "$3" "$9 }' | sort -f | sed 's/\ \[.*\]/\ \*/g' | sed 's/:/\ /g' | sed 's/\ [[:digit:]]\{2,5\}$/\ anonymous_port/g' | uniq >> /tmp/slask 497 | fi 498 | # Sort by application: 499 | less /tmp/slask | sort -f -k 3 > "$FILE_LISTEN" 500 | # Add a line at the end so that we do not forget the last line during printout 501 | echo "" >> "$FILE_LISTEN" 502 | # One can check the IP-address with this sed-line: sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}:.\{2,15\}->//g' (possible future development) 503 | 504 | # Create a file whose existence tells if the launchd-part of open_ports is running (otherwise warn the user) 505 | if [ "$TIMER_METHOD" = "launchd" ]; then 506 | if [ -z "`launchctl list | grep 'se.lth.cs.open_ports'`" ]; then 507 | touch "$LAUNCHD_FLAG" 508 | else 509 | /bin/rm -f "$LAUNCHD_FLAG" 2> /dev/null 510 | fi 511 | fi 512 | 513 | # On Mac OS X: see if there is any system software updates 514 | # Check this every three hours 515 | if [ "$OS" = "Darwin" ]; then 516 | if [ -z "`find $SoftUpd -type f -mtime -3h 2> /dev/null`" ]; then 517 | softwareupdate -l 1> "$SoftUpd" 2> /dev/null 518 | chmod 644 "$SoftUpd" 2> /dev/null 519 | fi 520 | fi 521 | 522 | # Make sure there is a GeoLookupDir and it has usable permissions. 523 | # This could most probably be made much better 524 | [[ -d "$GeoLookupDir" ]] || mkdir $GeoLookupDir 2>/dev/null 525 | chmod 777 "$GeoLookupDir" 2> /dev/null 526 | chmod 666 "$GeoLookupDir/*" 2> /dev/null 527 | 528 | # Make sure the Countries-file exist. Fetch it otherwise 529 | # This can probably be removed in 2015 530 | if [ ! -f "$CountryList" ]; then 531 | curl -s -f -e "$ScriptName ver:$VER" -o /tmp/Countries.txt "$OpenPortsURL"/Countries.txt 2>/dev/null 532 | curl -s -f -e "$ScriptName ver:$VER" -o /tmp/Countries.txt.sha1 "$OpenPortsURL"/Countries.txt.sha1 2>/dev/null 533 | ERR=$? 534 | if [ "$ERR" -eq 0 ] ; then 535 | if [ "$(openssl sha1 /tmp/Countries.txt | awk '{ print $2 }')" = "$(less /tmp/Countries.txt.sha1)" ]; then 536 | /bin/mv /tmp/Countries.txt "$CountryList" 537 | /bin/rm /tmp/Countries.txt.sha1 2>/dev/null 538 | echo "$(date): The file \"Countries.txt\" was installed" >> "$OP_LOGG" 539 | fi 540 | else 541 | echo "$(date): The \"Countries.txt\" could not be fetched (Err: \"${ERR}\")" >> "$OP_LOGG" 542 | fi 543 | fi 544 | 545 | 546 | # Clean up leftover-files in /tmp 547 | /bin/rm -f /tmp/"$ScriptName" /tmp/"$ScriptName".sha1 2>/dev/null 548 | 549 | printf " Done! (View data by running the script as any other user)\n" 550 | 551 | exit 0 552 | fi 553 | # ================================================================================================================= 554 | # ================================================================================================================= 555 | # =============================== E N D O F D A T A G E N E R A T I O N ================================= 556 | # ================================================================================================================= 557 | # ================================================================================================================= 558 | # 559 | # 560 | # Everything below is run by the user 561 | 562 | 563 | # Clean the GeoLocate cache for old entries every 7 days 564 | if [ -z "$(find $BINDIR/open_ports.sh -type f ${MTIME7d} 2> /dev/null)" ]; then 565 | CleanGeoLocate 566 | # touch the script so we come to this part of the script ever again 567 | touch "$BINDIR/$ScriptName" 2>/dev/null 568 | fi 569 | 570 | 571 | # ---------------------------------------------------------------------------------------------------- 572 | # 573 | 574 | # Print warnings if something is not right 575 | 576 | # Check if there is any data file: warn the user and quit otherwise 577 | if [ ! -f "$FILE4" ]; then 578 | printf "${ESC}${RedFont}mWARNING: No datafile! Run the command as \"root\" to generate data! (Or install the \"launchd\"-component)$Reset\n\nWill now exit!\n" 579 | exit 0 580 | fi 581 | 582 | # Check to see if the launchd-part is running. Warn the user otherwise 583 | if [ "$TIMER_METHOD" = "launchd" ]; then 584 | if [ -f "$LAUNCHD_FLAG" ]; then 585 | printf "${ESC}${RedFont}mWARNING: The \"launchd\"-component of \"open_ports.sh\" is NOT RUNNING!!!\n\n$Reset" 586 | fi 587 | elif [ "$TIMER_METHOD" = "systemd" ]; then 588 | if [ "$(systemctl is-active open-ports.timer)" != "active" ]; then 589 | printf "${ESC}${RedFont}mWARNING: The \"systemd\"-component of \"open_ports.sh\" is NOT RUNNING!!!\n\n$Reset" 590 | fi 591 | fi 592 | 593 | # Se that the datafiles are created within the last hour. Otherwise tell the user about it! 594 | if [ -z "$(find $FILE4 -type f ${MTIME60m} 2> /dev/null)" ]; then 595 | if [ "$TIMER_METHOD" = "launchd" ]; then 596 | printf "${ESC}${RedFont}mWARNING: The datafile is older than 1 hour; make sure the \"launchd\"-component (\"se.lth.cs.open_ports\", located in \"/Library/LaunchDaemons\")\n$Reset" 597 | elif [ "$TIMER_METHOD" = "systemd" ]; then 598 | printf "${ESC}${RedFont}mWARNING: The datafile is older than 1 hour; make sure the \"systemd\"-component (\"open-ports.timer\", located in \"/etc/systemd/system\")\n$Reset" 599 | fi 600 | printf "${ESC}${RedFont}mis working properly! The information presented here is not current!!$Reset\n\n\n" 601 | fi 602 | 603 | # If we don't have an IP-address ($DEFAULT_INTERFACE = "") warn the user!! 604 | if [ -z "$DEFAULT_INTERFACE" ]; then 605 | printf "${ESC}${RedFont}mWARNING: No IP-address detected!!!\n\n$Reset" 606 | fi 607 | 608 | # Find out if is IPv6 is configured 609 | if [ -z "$(/sbin/ifconfig $DEFAULT_INTERFACE | grep inet6)" ]; then 610 | IPv6="f" 611 | else 612 | IPv6="t" 613 | fi 614 | 615 | # End print warnings 616 | # 617 | # ---------------------------------------------------------------------------------------------------- 618 | 619 | 620 | # Prepare what is to be presented regarding the IP-address (if we are behind a NAT it should be prented) 621 | if [ "$(less $EXTERN)" = "$MY_IP_ADDRESS" ]; then 622 | IP_ADDRESS_Display="$MY_IP_ADDRESS" 623 | else 624 | IP_ADDRESS_Display="NAT: $MY_IP_ADDRESS / $(less $EXTERN)" 625 | fi 626 | 627 | # Find out which distro we are running 628 | # On Mac OS X, use the command "sw_vers" 629 | # On linux, use the command "lsb_release" if available, otherwise use the file "/etc/issue" 630 | if [ "$OS" = "Darwin" ]; then 631 | SW_VERS="$(sw_vers | grep ProductName | cut -d: -f2 | tr -d "\t") $(sw_vers | grep ProductVersion | awk '{print $2}' | tr '\n' ' ')" 632 | # Find out if it's a server 633 | # First step: does the name fromsw_vers include "server"? 634 | if [ -z "$(echo "$SW_VERS" | grep -i server)" ]; then 635 | # If not, it may still be a server. Beginning with OS X 10.8 all versions include the command serverinfo: 636 | serverinfo --software 1>/dev/null 637 | # Exit code 0 = server; 1 = NOT server 638 | ServSoft=$? 639 | if [ $ServSoft -eq 0 ]; then 640 | # Is it configured? 641 | serverinfo --configured 1>/dev/null 642 | ServConfigured=$? 643 | if [ $ServConfigured -eq 0 ]; then 644 | SW_VERS="$SW_VERS ($(serverinfo --productname) $(serverinfo --shortversion))" 645 | else 646 | SW_VERS="$SW_VERS ($(serverinfo --productname) $(serverinfo --shortversion) - unconfigured)" 647 | fi 648 | fi 649 | fi 650 | elif [ "$OS" = "Linux" ]; then 651 | if [ -x /bin/lsb_release ]; then 652 | SW_VERS="$(lsb_release -a 2> /dev/null | grep Description | cut -d: -f2 | sed 's/^\t*//g')" 653 | elif [ -f /etc/issue ]; then 654 | SW_VERS="$(grep -v "^$" /etc/issue | head -1 | cut -d\\ -f1 | head -1)" 655 | else 656 | SW_VERS="Unknown Linux distribution" 657 | fi 658 | fi 659 | 660 | 661 | # 662 | # Print the head 663 | 664 | # First, print if there is an update for the script available 665 | printf "$UpdateMessage" 666 | printf "${ESC}${BlackBack};${WhiteFont}mHostname:${ESC}${WhiteBack};${BlackFont}m $(hostname) ($IP_ADDRESS_Display) ${Reset} ${ESC}${BlackBack};${WhiteFont}mRunning:${ESC}${WhiteBack};${BlackFont}m $SW_VERS ${Reset} ${ESC}${BlackBack};${WhiteFont}mUptime:${ESC}${WhiteBack};${BlackFont}m $(uptime | cut -d, -f1 | sed -E 's/^.*up\ //g') ${Reset}\n" 667 | 668 | # If a Mac, print information about all configured interfaces 669 | [ "$OS" = "Darwin" ] && PrintAllInterfaces 670 | 671 | echo 672 | # System Software Update, Mac OS X: 673 | # Report the available software updates (from the file/tmp/swu.temp, generated by this script) 674 | # 675 | # That file typically contains this: 676 | # Software Update Tool 677 | # Copyright 2002-2009 Apple 678 | # 679 | # Software Update found the following new or updated software: 680 | # * MacOSXUpd10.6.5-10.6.5 681 | # Mac OS X Update (10.6.5), 505193K [recommended] [restart] 682 | # * iTunesX-10.1.1 683 | # iTunes (10.1.1), 91023K [recommended] 684 | # * XcodeUpdate-3.2.5 685 | # Xcode Update (3.2.5), 604086K [recommended] 686 | # * Safari5.0.3SnowLeopard-5.0.3 687 | # Safari (5.0.3), 38316K [recommended] [restart] 688 | # * AirPortUtility-5.5.2 689 | # AirPort Utility (5.5.2), 11990K [recommended] 690 | 691 | # From this we will cut away everything but this: 692 | # Mac OS X Update (10.6.5) [restart] 693 | # iTunes (10.1.1) 694 | # Xcode Update (3.2.5) 695 | # Safari (5.0.3) [restart] 696 | # AirPort Utility (5.5.2) 697 | if [ "$OS" = "Darwin" ]; then 698 | if [ "$(grep 'Software Update found the following new or updated software' $SoftUpd)" ]; then 699 | printf "${ESC}${BoldFace};${BlackFont};${YellowBack}mThe following software update is available:${Reset}\n${ESC}${YellowFont}m" 700 | less "$SoftUpd" | egrep -v "^Software Update Tool|^Copyright 2002-2009 Apple|^$" | awk ' 701 | /^\ *\*\ / { 702 | record="t";next; 703 | } 704 | record == "t" { gsub("^[ \t]*","");gsub(", [0-9]*K \\[[^\\]]*\\]","");print "• "$0;record="f";next}' 705 | printf "${Reset}\n" 706 | fi 707 | fi 708 | 709 | # End print of the head 710 | 711 | # ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 712 | # Print the ETSABLISHED-files 713 | for i in 4 6 714 | do 715 | if [ "$i" = "4" ]; then 716 | exec 4<"$FILE4" 717 | else 718 | exec 6<"$FILE6" 719 | fi 720 | 721 | # Prepare the date/time-string. Example: “18 Sep 10:29” 722 | [[ "$OS" = "Darwin" ]] && DATE=$(ls -ls $(dirname "$FILE4"/ip"$i".txt) | awk '{ print $7" "$8" "$9 }') 723 | [[ "$OS" = "Linux" ]] && DATE=$(ls -ls --time-style=+%Y-%m-%d\ %H:%M $(dirname "$FILE4"/ip"$i".txt) | awk '{ print $7" "$8 }') 724 | printf "${ESC}${BoldFace}mEstablished IPv$i-connections:$Reset ($DATE) $(if [ "$i" = "4" ]; then printf "${ESC}${ItalicFace}m(Explanation: Normal$Reset, ${ESC}${GreenFont};${ItalicFace}mSafe protocol$Reset, ${ESC}${CyanFont};${ItalicFace}mAmbiguous DNS$Reset, ${ESC}${RedFont};${ItalicFace}mNo DNS-name$Reset, ${ESC}${RedBack};${WhiteFont};${ItalicFace}mUser is root$Reset${ESC}${ItalicFace}m)$Reset"; fi)\n" 725 | if [ "$IPv6" = "f" -a "$i" -eq 6 ]; then 726 | printf "${ESC}${ItalicFace};${YellowFont}mIPv6 is not configured for interface \"${DEFAULT_INTERFACE}\"$Reset" 727 | else 728 | echo 729 | # Print different headers if $PREFIX/$GeoLookupKey exist or not 730 | if [ -n "$GeoLookupKey" ]; then 731 | printf "${ESC}${UnderlineFace};${YellowFont}m${Formatstring1}${Reset}\n" "Program" "Port" "User" "#" " " "Hostname $(if [ ! "$DOMAIN" = "" ]; then echo "[.$DOMAIN]"; fi)" "Country" "City" 732 | else 733 | printf "${ESC}${UnderlineFace};${YellowFont}m${Formatstring2}${Reset}\n" "Program" "Port" "User" "#" " " "Hostname $(if [ ! "$DOMAIN" = "" ]; then echo "[.$DOMAIN]"; fi)" 734 | fi 735 | if [ -s "$PREFIX/ip$i.txt" ]; then 736 | while read -u $i COUNT PROGRAM USERR IP PORT 737 | # Exmple lines: 738 | # IPv4: 1 2BUA8C4S2C.com. peterm 127.0.0.1 49206 739 | # IPv6: 1 Screen\x20Sharing peterm 192.168.1.99:63835->130.235.16.211:rfb 740 | do 741 | # Zero the colors: 742 | BGColor="$RES" 743 | Face="$RES" 744 | FontColor="$RES" 745 | 746 | # lsof +c 0 replaces " " in application names with "x20"; change back! 747 | PROGRAM="$(echo $PROGRAM | sed 's/x20/\ /g')" 748 | # If the text is too wide, shorten it 749 | if [ $(echo $PROGRAM | wc -c) -gt 23 ]; then 750 | PROGRAM="$(echo $PROGRAM | sed 's/x20/\ /g' | cut -c -20)..." 751 | fi 752 | 753 | # Find out the hostname for $IP. Cut of the trailing dot 754 | # Gives: $HOSTNAME 755 | # Also gives PrivateAddress="Yes" if it's a private address (192.168.*.*, 172.16.*.*, 10.*.*.*, 169.254.*.*) 756 | # (REMOVED) VERY DIRTY: "$(echo $IP | cut -d: -f1)" 757 | GetDNS "$IP" 758 | # GetDNS "$(echo $IP | cut -d: -f1)" 759 | 760 | # Find the geo location (also deal with localhost!) 761 | # If $IP exist in $GeoLookupDir - get the country and city right away 762 | # otherwise, 763 | # if IP is 127.0.0.1 764 | # AND we are beind a NAT-router (MY_IP_ADDRESS is in the {192.168|172.16|10}-series); 765 | # find the external address with whatsmyip.com and store it along with country/city 766 | # otherwise 767 | # look up the geodata for the default address for the computer 768 | # otherwise 769 | # look up the IP address and store in the temporary cache 770 | # get the country and city and store in $IP_CACHE 771 | # (DIRT REMOVED) VERY DIRTY: "$(echo $IP | cut -d: -f1)" 772 | if [ -r "${GeoLookupDir}/${IP}.txt" ]; then 773 | GetCityCountry $IP 774 | else 775 | if [ "$IP" = "127.0.0.1" ]; then 776 | if [ -n "$NAT" ]; then 777 | PerformGeoLookup "$(less $EXTERN)" 778 | echo "$City:$Country" > "${GeoLookupDir}/${IP}.txt" 779 | else 780 | PerformGeoLookup $MY_IP_ADDRESS 781 | fi 782 | else 783 | # PerformGeoLookup $IP 784 | PerformGeoLookup "$(echo $IP | cut -d: -f1)" 785 | fi 786 | fi 787 | 788 | # Set the colors: 789 | # If user is root - red background and white text! 790 | if [ "$USERR" = "root" ]; then 791 | BGColor="$RedBack" 792 | FontColor="$WhiteFont" 793 | fi 794 | # If it's a safe protocol - green text 795 | if [ ! -z "$(echo $PORT | egrep 'ssh|https|imaps|smtps|scp|sftp')" -o ! -z "$(echo $PROGRAM | egrep 'sshd')" ]; then 796 | FontColor="$GreenFont" 797 | fi 798 | # No DNS-name AND we are not in a home environment - red text and explain 799 | if [ -n "$(echo "$HOSTNAME" | grep 'DNS timeout')" -a -z "$NAT" ]; then 800 | #HOSTNAME="$IP can’t be found in reverse-lookup" 801 | FontColor="$RedFont" 802 | fi 803 | # many answers to the reverse DNS lookup? Blue text and explain 804 | # Otherwise: print 805 | if [ "$(echo $HOSTNAME | wc -w)" -gt "1" -a -z "$(echo $HOSTNAME | grep 'DNS timeout')" -a "$PrivateAddress" = "No" ]; then 806 | FontColor="$CyanFont" 807 | HOSTN="$IP = \"$(echo $HOSTNAME | awk '{ print $1 }')\" and `echo $(( $(echo $HOSTNAME | wc | awk '{ print $2 }') - 1 ))` more names" 808 | HOSTNAME="$HOSTN" 809 | fi 810 | # If background is red AND text is red? Blink with white text! 811 | if [ "$BGColor" = "41" -a "$FontColor" = "31" ]; then 812 | FontColor="$WhiteFont" 813 | Face="$SlowBlink" 814 | fi 815 | # Print the line! 816 | if [ -n "$GeoLookupKey" ]; then 817 | printf "${ESC}${Face};${BGColor};${FontColor}m$Formatstring1$Reset\n" "$PROGRAM" "$PORT" "$USERR" "$COUNT" " " "${HOSTNAME//.$DOMAIN}" "$Country" "$City" 818 | else 819 | printf "${ESC}${Face};${BGColor};${FontColor}m$Formatstring2$Reset\n" "$PROGRAM" "$PORT" "$USERR" "$COUNT" " " "${HOSTNAME//.$DOMAIN}" 820 | fi 821 | done 822 | else 823 | echo "No established IPv$i-connections" 824 | fi 825 | fi 826 | echo 827 | echo 828 | done 829 | 830 | # End print of ESTABLISHED 831 | # ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 832 | 833 | 834 | 835 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 836 | # Print the LISTEN-file 837 | LastIPv4="" 838 | LastIPv6="" 839 | LastProgram="" 840 | LastUser="" 841 | LastRange="" 842 | LastPort="" 843 | exec 5<"$FILE_LISTEN" 844 | if [ -s "$FILE_LISTEN" ]; then 845 | [[ "$OS" = "Darwin" ]] && DATE=$(ls -ls "$FILE_LISTEN" | awk '{ print $7" "$8" "$9 }') 846 | [[ "$OS" = "Linux" ]] && DATE=$(ls -ls --time-style=+%Y-%m-%d\ %H:%M "$FILE_LISTEN" | awk '{ print $7" "$8 }') 847 | printf "\n\n${ESC}${BoldFace}mListening ports:$Reset ($DATE)\n\n" 848 | printf "${ESC}${UnderlineFace};${YellowFont}m$FormatstringListen$Reset\n" "IPv4" "IPv6" "Program" "User" "Port#" " " "PortName" "Servicerange" 849 | while read -u 5 IPv4 IPv6 PROGRAM USERR RANGE PORT 850 | do 851 | # Reset the colors: 852 | BGColor="$RES" 853 | Face="$RES" 854 | FontColor="$RES" 855 | 856 | # lsof +c 0 replaces " " in application names with "x20"; change back! 857 | PROGRAM="$(echo $PROGRAM | sed 's/x20/\ /g')" 858 | # If the text is too wide, shorten it 859 | if [ $(echo $PROGRAM | wc -c) -gt 16 ]; then 860 | PROGRAM="$(echo $PROGRAM | sed 's/x20/\ /g' | cut -c -15)..." 861 | fi 862 | #PROGR=`echo $PROGRAM | sed 's/x20/\ /g'` 863 | # If the lines are the same: do nothing more than to set both 4 and 6 when it is to be printed the next turn around 864 | if [[ "$LastProgram" = "$PROGRAM" && "$LastUser" = "$USERR" && "$LastPort" = "$PORT" && "$LastRange" = "$RANGE" ]]; then 865 | export LastIPv4="4" 866 | export LastIPv6="6" 867 | else 868 | # This turn is will be printed 869 | 870 | # If LastProgram is NOT empty (then assume the other are as well; first turn around - do not print!) 871 | # the choose colors 872 | if [ ! -z "$LastProgram" ]; then 873 | # If user is root - red background and white text! 874 | if [ "$LastUser" = "root" ]; then 875 | BGColor="$RedBack" 876 | FontColor="$WhiteFont" 877 | fi 878 | # Safe protocol - green text 879 | if [ ! -z "`echo $LastPort | egrep 'ssh|https|imaps|smtps|scp|sftp'`" -o ! -z "`echo $LastProgram | egrep 'sshd'`" ]; then 880 | FontColor="$GreenFont" 881 | fi 882 | # Print!! 883 | printf "${ESC}${BGColor};${FontColor}m$FormatstringListen$Reset\n" "$LastIPv4" "$LastIPv6" "$LastProgram" "$LastUser" "`grep "^$LastPort\b" /etc/services | head -1 | awk '{ print $2 }' | cut -d/ -f1`" " " "`echo $LastPort | sed 's/_/\ /g'`" "$LastRange" 884 | fi 885 | LastIPv4="$IPv4" 886 | LastIPv6="$IPv6" 887 | fi 888 | LastProgram="$PROGRAM" 889 | LastUser="$USERR" 890 | LastPort="$PORT" 891 | LastRange="$RANGE" 892 | done 893 | else 894 | echo "No ports open for listening" 895 | fi 896 | 897 | # End print of LISTEN 898 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 899 | 900 | exit 0 901 | --------------------------------------------------------------------------------