Hello community, here is the log from the commit of package fonehome for openSUSE:Factory checked in at 2013-12-11 15:39:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fonehome (Old) and /work/SRC/openSUSE:Factory/.fonehome.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fonehome" Changes: -------- --- /work/SRC/openSUSE:Factory/fonehome/fonehome.changes 2013-02-20 09:23:56.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.fonehome.new/fonehome.changes 2013-12-11 15:39:50.000000000 +0100 @@ -1,0 +2,7 @@ +Tue Dec 10 21:05:40 UTC 2013 - [email protected] + +- Upgrade to version 1.0.31 + + Add support for connecting to multiple servers (issue #1) + + Log connection attempts and status to syslog (issue #2) + +------------------------------------------------------------------- Old: ---- fonehome-1.0.28.tar.gz New: ---- fonehome-1.0.31.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fonehome.spec ++++++ --- /var/tmp/diff_new_pack.uWoGu1/_old 2013-12-11 15:39:51.000000000 +0100 +++ /var/tmp/diff_new_pack.uWoGu1/_new 2013-12-11 15:39:51.000000000 +0100 @@ -26,6 +26,7 @@ %define keyfile %{confdir}/%{name}.key %define hostsfile %{confdir}/%{name}.hosts %define retrydelay 30 +%define syslogfac daemon # server side %define username %{name} @@ -40,7 +41,7 @@ %define authkeys_options no-X11-forwarding,no-agent-forwarding,no-pty,permitopen="0.0.0.0:9",command="sleep 99999d" Name: fonehome -Version: 1.0.28 +Version: 1.0.31 Release: 0 Summary: Remote access to machines behind firewalls License: Apache-2.0 @@ -49,7 +50,9 @@ BuildArch: noarch Source: %{name}-%{version}.tar.gz Url: http://code.google.com/p/%{name}/ +Requires: findutils Requires: openssh +Requires: sed %description fonehome allows remote access to machines behind firewalls using SSH @@ -81,7 +84,8 @@ -e 's|@fonehomehosts@|%{hostsfile}|g' \ -e 's|@fonehomeretry@|%{retrydelay}|g' \ -e 's|@fonehomeinit@|%{initfile}|g' \ - -e 's|@fonehomescript@|%{scriptfile}|g' + -e 's|@fonehomescript@|%{scriptfile}|g' \ + -e 's|@fonehomelogfac@|%{syslogfac}|g' } subst < src/conf/fonehome.conf.sample > fonehome.conf.sample subst < src/conf/fonehome-ports.conf.sample > fonehome-ports.conf.sample ++++++ fonehome-1.0.28.tar.gz -> fonehome-1.0.31.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fonehome-1.0.28/CHANGES new/fonehome-1.0.31/CHANGES --- old/fonehome-1.0.28/CHANGES 2013-02-18 17:20:47.000000000 +0100 +++ new/fonehome-1.0.31/CHANGES 2013-12-10 22:03:01.000000000 +0100 @@ -1,3 +1,7 @@ +Version 1.0.31 Released December 10, 2013 + + - Add support for connecting to multiple servers (issue #1) + - Log connection attempts and status to syslog (issue #2) Version 1.0.28 Released February 18, 2013 @@ -23,4 +27,4 @@ - Initial release -$Id: CHANGES 28 2013-02-18 16:20:12Z archie.cobbs $ +$Id: CHANGES 31 2013-12-10 21:02:32Z archie.cobbs $ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fonehome-1.0.28/src/conf/fonehome.conf.sample new/fonehome-1.0.31/src/conf/fonehome.conf.sample --- old/fonehome-1.0.28/src/conf/fonehome.conf.sample 2013-02-18 17:20:47.000000000 +0100 +++ new/fonehome-1.0.31/src/conf/fonehome.conf.sample 2013-12-10 22:03:01.000000000 +0100 @@ -1,20 +1,45 @@ # $Id$ # -# This is a configuration file for the fonehome client. +# This is a configuration file for the fonehome client and will be sourced as bash(1) input. # See http://code.google.com/p/fonehome/ for details. # -# Configure the server to connect to (REQUIRED). +# Configure the server(s) to connect to (REQUIRED). +# +# Note: SERVER may be optionally declared as bash(1) array variables to connect to multiple servers. +# +# If so, then USERNAME, KEY_FILE, SSH_FLAGS, and RETRY_DELAY are also treated as arrays, and the i'th +# element in those arrays is used with the i'th element in $SERVER array. If any of these other array +# variables are shorter than $SERVER, then the last element in the array is used repeatedly, and if +# any of these other variables are not bash arrays, they are converted into an array of length one. +# Therefore, setting a simple non-array value results in that value being used for all servers. +# +# For example, here are three servers with three different usernames but sharing the same private key: +# +# SERVER=(serv1.example.com serv2.example.com serv3.example.com) +# USERNAME=(user1 user2 user3) +# KEY_FILE='@fonehomekey@' +# #SERVER='myhost.example.com' # Configure SSH command line flags. This minimal example allows reverse SSH connections via port 1234 on the server. # Consider also: -oCompression=yes, -oCheckHostIP=yes, -oLogLevel=.... See man ssh_config(5) for a complete list. SSH_FLAGS='-R1234:localhost:22' -# Other stuff you can configure (with defaults shown) +# SSH connection username USERNAME='@fonehomeuser@' + +# SSH connection private key file (should be unencrypted and readable only by root) KEY_FILE='@fonehomekey@' + +# How long to pause after a failed connection attempt or a disconnection RETRY_DELAY='@fonehomeretry@' -KNOWN_HOSTS_FILE="@fonehomehosts@" + +# How should fonehome log to syslog(3) +SYSLOG_TAG='@fonehomename@' +SYSLOG_FACILITY='@fonehomelogfac@' + +# SSH known hosts file. You must run `fonehome -I' once to initialize this file. +KNOWN_HOSTS_FILE='@fonehomehosts@' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fonehome-1.0.28/src/man/fonehome.1 new/fonehome-1.0.31/src/man/fonehome.1 --- old/fonehome-1.0.28/src/man/fonehome.1 2013-02-18 17:20:47.000000000 +0100 +++ new/fonehome-1.0.31/src/man/fonehome.1 2013-12-10 22:03:01.000000000 +0100 @@ -22,21 +22,28 @@ program. It creates a persistent no-pty .Xr ssh 1 -connection to a fonehome server. -Normal and reverse port forwarding is setup according to the configuration in +connection to one or more fonehome servers, with normal and reverse port forwarding +setup according to the configuration in .Pa @fonehomeconf@ . +This allows private, bi-directional connections between the fonehome client and server, +while keeping those connections fully secured, without requiring any firewall setup. +.Pp +.Nm +is useful in situations where you have several machines +deployed in the field and want to maintain secure access to them from a central +operations server without any firewall hassles. .Pp Normally .Nm is run as a daemon from .Pa @fonehomeinit@ . However, upon first installation (or whenever a server's host key changes), -an initialization step must be performed by running +a manual initialization step must be performed by running .Nm manually with the .Fl I flag. -This step allows the administrator to confirm and accept the server's host key. +This allows the administrator to confirm and accept the server host key(s). .Sh OPTIONS .Bl -tag -width Ds .It Fl f Ar config-file @@ -45,14 +52,80 @@ .It Fl I Perform first-time initialization when connecting to a new server. .El +.Sh CONFIGURATION +The configuration file is a +.Xr bash 1 +source file that defines the following shell variables: +.Bl -tag -width Ds +.It Pa SERVER +Defines the host to connect to. +This is the only variable that is strictly required. +.It Pa SSH_FLAGS +.Xr ssh 1 +command line flags to use with the connection. +Typically this will contain reverse-forwarded ports to allow connections back from +the server to the client. +.It Pa USERNAME +SSH username. +Default is +.Ar @fonehomeuser@ . +.It Pa KEY_FILE +File containing the SSH private key. +This file must be unencrypted to allow for unattended operation; however, +it should be readable only by root. +Default is +.Ar @fonehomekey@ . +.It Pa RETRY_DELAY +How long (in seconds) to pause between connection attempts. +Default is +.Ar @fonehomeretry@ +seconds. +.It Pa SYSLOG_TAG +Identifier to use when logging to +.Xr syslog 3 . +Default is +.Ar @fonehomename@ . +.It Pa SYSLOG_FACILITY +Facility to use when logging to +.Xr syslog 3 . +Default is +.Ar @fonehomelogfac@ . +.It Pa KNOWN_HOSTS_FILE +SSH known hosts file used to store recognized server public keys. +Default is +.Ar @fonehomehosts@ . +.El +.Sh MULTIPLE SERVERS +.Nm +suports connecting to multiple servers. +To enable multi-server support, simply declare +.Pa SERVER +as a +.Xr bash 1 +array variable. +Then a separate connection will be maintained to each server in the array. +.Pp +When multiple servers are configured, the +.Pa USERNAME , +.Pa SSH_FLAGS , +.Pa KEY_FILE , +and +.Pa RETRY_DELAY +variables may also be declared as arrays, in which case the corresponding +array elements will be used for each server. +If these variables are not arrays, or are shorter than the +.Pa SERVER +array, the last value will be used repeatedly. +Therefore, setting a simple (non-array) value results in that value being used for all servers. .Sh FILES .Bl -tag -width Ds -compact .It Pa @fonehomeconf@ Default configuration file. .It Pa @fonehomekey@ -Private SSH key file used to authenticate to the server. +Default private SSH key file used to authenticate to the server. .It Pa @fonehomehosts@ -SSH known hosts file used to store and verify the server's public key. +Default SSH known hosts file used to store and verify the server's public key. +.El .Sh SEE ALSO .Xr ssh 1 . .Rs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fonehome-1.0.28/src/scripts/fonehome.sh new/fonehome-1.0.31/src/scripts/fonehome.sh --- old/fonehome-1.0.28/src/scripts/fonehome.sh 2013-02-18 17:20:47.000000000 +0100 +++ new/fonehome-1.0.31/src/scripts/fonehome.sh 2013-12-10 22:03:01.000000000 +0100 @@ -1,13 +1,16 @@ #!/bin/bash -# $Id: fonehome.sh 2 2011-12-27 19:44:34Z archie.cobbs $ +# $Id: fonehome.sh 29 2013-12-10 20:55:18Z archie.cobbs $ # Set constants and defaults NAME='@fonehomename@' USERNAME='@fonehomeuser@' CONFIG_FILE='@fonehomeconf@' KEY_FILE='@fonehomekey@' -RETRY_DELAY="@fonehomeretry@" -KNOWN_HOSTS_FILE="@fonehomehosts@" +RETRY_DELAY='@fonehomeretry@' +KNOWN_HOSTS_FILE='@fonehomehosts@' +FACILITY_PATTERN='^(auth|authpriv|cron|daemon|ftp|lpr|mail|news|security|user|uucp|local[0-7])$' +SYSLOG_TAG='@fonehomename@' +SYSLOG_FACILITY='@fonehomelogfac@' # Usage message usage() @@ -20,21 +23,37 @@ } # Log functions -log() +perr() { echo ${NAME}: ${1+"$@"} 1>&2 } +log() +{ + LEVEL="${1}" + shift + logger -t "${SYSLOG_TAG}" -p "${SYSLOG_FACILITY}"."${LEVEL}" ${1+"$@"} + if [ -t 2 ]; then + perr ${1+"$@"} + fi +} + # Error function errout() { - log ${1+"$@"} + perr ${1+"$@"} + if ! [ -t 2 ]; then + log err ${1+"$@"} + fi exit 1 } # Bail on errors set -e +# Enable job control +set -m + # Parse flags passed in on the command line INITIALIZE="no" while [ ${#} -gt 0 ]; do @@ -75,56 +94,136 @@ ;; esac -# Read config file, which should set ${SSH_FLAGS} +# Read config file, which should set configuration variables if ! [ -r "${CONFIG_FILE}" ]; then errout "can't read config file: ${CONFIG_FILE}" fi . "${CONFIG_FILE}" # Verify required fields are set -if [ -z "${SERVER}" ]; then - errout "no server configured" +if ! [[ -v SERVER ]]; then + errout "no server(s) configured" fi -if [ -z "${USERNAME}" ]; then - errout "no username configured" +if ! [[ -v USERNAME ]]; then + errout "no username(s) configured" fi -if [ -z "${KEY_FILE}" -o ! -r "${KEY_FILE}" ]; then - errout "key file \`${KEY_FILE}' unreadable" +if ! [[ -v KEY_FILE ]]; then + errout "no key file(s) configured" fi + +# Sanity check syslog facility name +if ! echo "${SYSLOG_FACILITY}" | grep -qE "${FACILITY_PATTERN}"; then + errout "invalid syslog facility name \`${SYSLOG_FACILITY}'" +fi + +# Make config variables into arrays +declare -a SERVER USERNAME KEY_FILE SSH_FLAGS RETRY_DELAY + +# Get number of servers +declare -i NUM_SERVERS="${#SERVER[@]}" +declare -i i + +# Extend all arrays, repeating last element as necessary +for ((i=0; $i < "${NUM_SERVERS}"; i++)); do + if (( "${#USERNAME[@]}" <= $i )); then + USERNAME[$i]="${USERNAME[$(($i - 1))]}" + fi + if (( "${#KEY_FILE[@]}" <= $i )); then + KEY_FILE[$i]="${KEY_FILE[$(($i - 1))]}" + fi + if (( "${#SSH_FLAGS[@]}" <= $i )); then + SSH_FLAGS[$i]="${SSH_FLAGS[$(($i - 1))]}" + fi + if (( "${#RETRY_DELAY[@]}" <= $i )); then + RETRY_DELAY[$i]="${RETRY_DELAY[$(($i - 1))]}" + fi +done + +# Check required files if [ -z "${KNOWN_HOSTS_FILE}" ]; then errout "no known hosts file configured" fi -if [ "${INITIALIZE}" != 'yes' ]; then +if [ "${INITIALIZE}" = 'yes' ]; then + KNOWN_HOSTS_DIR=`dirname "${KNOWN_HOSTS_FILE}"` + if ! [ -w "${KNOWN_HOSTS_DIR}" ]; then + errout "known hosts file directory \`${KNOWN_HOSTS_DIR}' is unwritable" + fi +else if ! [ -r "${KNOWN_HOSTS_FILE}" ]; then errout "known hosts file \`${KNOWN_HOSTS_FILE}' unreadable; did you run once with \`-I' flag?" fi if ! [ -s "${KNOWN_HOSTS_FILE}" ]; then - errout "known hosts file \`${KNOWN_HOSTS_FILE}' is empty; did you run once with \`-I' flag?" + errout "known hosts file \`${KNOWN_HOSTS_FILE}' is empty; did you run once with \`-I' flag for each server?" fi fi +for ((i=0; $i < "${NUM_SERVERS}"; i++)); do + if ! [ -r "${KEY_FILE[$i]}" ]; then + errout "key file \`${KEY_FILE[$i]}' for server ${SERVER[$i]} is unreadable" + fi +done # Doing initialization? if [ "${INITIALIZE}" = "yes" ]; then - exec ssh -24xaT -oStrictHostKeyChecking=ask -oUserKnownHostsFile="${KNOWN_HOSTS_FILE}" \ - -oVisualHostKey=yes -oCheckHostIP=no -i "${KEY_FILE}" ${SSH_FLAGS} "${USERNAME}"@"${SERVER}" + for ((i=0; $i < "${NUM_SERVERS}"; i++)); do + perr "confirming server key for ${SERVER[$i]}" + ssh -24xaT -oStrictHostKeyChecking=ask -oUserKnownHostsFile="${KNOWN_HOSTS_FILE}" \ + -oVisualHostKey=yes -oCheckHostIP=no -i "${KEY_FILE[$i]}" ${SSH_FLAGS[$i]} "${USERNAME[$i]}"@"${SERVER[$i]}" + done + exit 0 fi -# Ensure background process is killed when this script is killed -set -m -trap killchild TERM INT -killchild() +# Subshell - there is one of these for each server +subshell() { - kill %% >/dev/null 2>&1 - exit + # Don't die on error + set +e + + # Which server am I? + INDEX="${1}" + + # Create temporary file to hold output of ssh(1) command + OUTPUT_FILE=`mktemp -q /tmp/fonehome.XXXXXXXX` + if [ $? -ne 0 ]; then + log error "can't create temporary file" + OUTPUT_FILE="/dev/null" + fi + + # Clean up output file on exit + trap "if [ \"${OUTPUT_FILE}\" != '/dev/null' ]; then rm -f \"${OUTPUT_FILE}\"; fi; exit" INT TERM + + # Connect to server; reconnect if we get disconnected + while true; do + log info initiating connection to "${SERVER[$INDEX]}" + ssh -24xaTnN -oBatchMode=yes -oExitOnForwardFailure=yes \ + -oStrictHostKeyChecking=yes -oUserKnownHostsFile="${KNOWN_HOSTS_FILE}" \ + -oServerAliveInterval=60 -oServerAliveCountMax=5 -oTCPKeepAlive=yes \ + -oCheckHostIP=no -i "${KEY_FILE[$INDEX]}" ${SSH_FLAGS[$INDEX]} "${USERNAME[$INDEX]}"@"${SERVER[$INDEX]}" >"${OUTPUT_FILE}" 2>&1 + if [ -s "${OUTPUT_FILE}" ]; then + log warn "connection to ${SERVER[$INDEX]} failed: `cat \"${OUTPUT_FILE}\"`" + else + log warn "connection to ${SERVER[$INDEX]} failed" + fi + sleep "${RETRY_DELAY[$INDEX]}" + done } -# Main loop -while true; do - ssh -24xaTnN -oBatchMode=yes -oExitOnForwardFailure=yes \ - -oStrictHostKeyChecking=yes -oUserKnownHostsFile="${KNOWN_HOSTS_FILE}" \ - -oServerAliveInterval=60 -oServerAliveCountMax=5 -oTCPKeepAlive=yes \ - -oCheckHostIP=no -i "${KEY_FILE}" ${SSH_FLAGS} "${USERNAME}"@"${SERVER}" >/dev/null 2>&1 & +# This function is used to ensure the subshells are killed when this script is killed +killshells() +{ + jobs -p | sed 's/^/-/g' | xargs -r kill -- + log info shutting down wait - sleep ${RETRY_DELAY} + exit +} + +# Clean up subshells on exit +trap killshells INT TERM + +# Start the subshells +for ((i=0; $i < "${NUM_SERVERS}"; i++)); do + subshell $i & done +# Now we just hang out +wait + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fonehome-1.0.28/xx.sh new/fonehome-1.0.31/xx.sh --- old/fonehome-1.0.28/xx.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/fonehome-1.0.31/xx.sh 2013-12-10 22:03:01.000000000 +0100 @@ -0,0 +1,69 @@ +#!/bin/bash + +foo="abc def" +declare -a foo +foo[1]="ghi jkl" +foo[2]="mno pqr" + +bar="zzz" +declare -a bar + +# Create PID array for sub-shells +declare -i NUM_SERVERS=3 +declare -a SHELL_PIDS + +if (( 5 <= 5 )); then + echo true +else + echo false +fi +exit + +# Ensure subshells are killed when this script is killed +set -m +trap killshells TERM INT +killshells() +{ + i=0 + while [[ $i < "${NUM_SERVERS}" ]]; do + PID="${SHELL_PIDS[$i]}" + if [ -n "${PID}" ]; then + echo "main shell killing subshell #$i having PID=${PID}..." 1>&2 + kill "${PID}" + fi + i=$(($i + 1)) + done + echo "main shell exiting" 1>&2 + exit +} + +# Subshell +subshell() +{ + INDEX="${1}" + PID="" + trap "echo \"subshell #$INDEX\"; kill %%; echo \"subshell $INDEX exiting\"; exit" TERM INT + echo subshell $INDEX started + declare -i j=0 + while [[ $j < 100 ]]; do + echo "subshell $INDEX starting sleep" + sleep 10 & + PID=$! + echo "subshell $INDEX waiting for sleep with PID=${PID}" + wait + j=$(($j + 1)) + done +} + +# Start subshells +for ((i=0; $i < "${NUM_SERVERS}"; i++)); do + echo "main shell forking subshell #$i" + subshell $i & + SHELL_PIDS[$i]=$! + echo "main shell forked subshell #$i with PID=${SHELL_PIDS[$i]}" +done + +while true; do + wait +done + -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
