<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cosine Jeremiah and his Musings &#187; Unix</title>
	<atom:link href="http://cosine.org/category/unix/feed/" rel="self" type="application/rss+xml" />
	<link>http://cosine.org</link>
	<description>Life and Ruby and Security</description>
	<lastBuildDate>Sat, 10 Apr 2010 08:48:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Multi-User Screen</title>
		<link>http://cosine.org/2007/10/23/multiuser-screen/</link>
		<comments>http://cosine.org/2007/10/23/multiuser-screen/#comments</comments>
		<pubDate>Tue, 23 Oct 2007 13:27:10 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/10/23/multiuser-screen/</guid>
		<description><![CDATA[Have you ever been jamming away on a Unix host&#8217;s command line and wish you could share your session with others?  Perhaps you could do so to show someone else something you found on the system?  Maybe you want that someone to type a password for you?  Or perhaps you need to [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever been jamming away on a Unix host&#8217;s command line and wish you could share your session with others?  Perhaps you could do so to show someone else something you found on the system?  Maybe you want that someone to type a password for you?  Or perhaps you need to share the experience of going through some prompts and how to answer them?  Recently there have been a myriad of technologies that can share windows and even whole desktops, but those programs are not always handy or appropriate.</p>
<p>Fortunately, the <a href="http://www.gnu.org/software/screen/">GNU Screen</a> program can share that command line session of yours with other users with accounts on the same Unix host.  Screen comes with a multi-user mode that allows them to connect to it.  Each user can be granted permissions to each window to view, interact, or issue other commands to Screen.  Here is a .screenrc file I have used to implement three groups of users: read-only users that can view all windows, read-write users that can also type in all windows, and an administrative user (the account that runs screen in my case) that retains all permissions within Screen.</p>
<pre>
multiuser on

aclchg READERS +r-wx &#34;#&#34;
aclchg READERS -rwx &#34;?&#34;
aclchg READERS +x colon,license,windows,next,prev,select,other,detach,suspend,redisplay,lastmsg,windowlist,help,stuff

aclchg WRITERS +rw-x &#34;#&#34;
aclchg WRITERS -rwx &#34;?&#34;
aclchg WRITERS +x colon,license,windows,next,prev,select,other,detach,suspend,redisplay,lastmsg,windowlist,help,stuff

aclgrp watcher1 READERS
aclgrp watcher2 READERS
aclgrp trusted1 WRITERS
aclgrp trusted2 WRITERS

aclumask &#34;*&#34;-rwx cosine+rwx READERS+r-wx WRITERS+rw-x &#34;?&#34;-rwx &#34;??&#34;-rwx
</pre>
<p><!-- adman --></p>
<p>In this example, the administrative user is <code>cosine</code>.  The read-only users <code>watcher1</code> and <code>watcher2</code> are in the <code>READERS</code> group.  Likewise, the read-write users <code>trusted1</code> and <code>trusted2</code> are in the <code>WRITERS</code> group.  Users are placed in groups with the <code>aclgrp</code> command.</p>
<p>The other commands to set this up can be understood with a careful read of Screen&#8217;s man page.  The short of it is that for <code>READERS</code> we give read access but no write or execute (<code>+r-wx</code>) for all windows (<code>#</code>), then we do not allow any access (<code>-rwx</code>) to any Screen commands.  Next we do enable access (<code>+x</code>) to a reasonable set of Screen commands necessary for navigation and comfortable viewing&mdash;otherwise Screen would not allow the user to change windows, exit his session, or a few other commands Screen users take for granted.  The <code>aclumask</code> command provides a similar level of coverage to windows that are yet to be created.  The <code>WRITERS</code> group is given similar permissions, except users in that group are also allowed to write (i.e. type things) into all windows.</p>
<p>If we wanted to create an <code>ADMINS</code> group that had full control of screen (able to create new windows and execute arbitrary screen commands), we could do so by replacing the <code>aclumask</code> command with another that replaces the mention of the <code>cosine</code> user with an <code>ADMINS</code> group, adding a pair of <code>aclchg</code> commands to grant this group access to everything, and then adding some users to the group:</p>
<pre>
aclchg ADMINS +rwx &#34;#&#34;
aclchg ADMINS +rwx &#34;?&#34;

aclgrp cosine ADMINS
aclgrp admin1 ADMINS
aclgrp admin2 ADMINS

aclumask &#34;*&#34;-rwx ADMINS+rwx READERS+r-wx WRITERS+rw-x &#34;?&#34;-rwx &#34;??&#34;-rwx
</pre>
<p>If you begin experimenting with these &#8220;acl&#8221; commands in Screen, do make sure you test your configurations before using them.  Screen did not make these commands particularly user-friendly, and they do not always behave how you might think they do.  They feel like they were bolted onto the program as an afterthought, and if you have been reading my blog for very long <a href="http://www.cosine.org/2007/09/14/bolting-security/">you know how I feel about <em>that</em></a>.  I would not use Screen&#8217;s multi-user mode for any high-security application.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/10/23/multiuser-screen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Answers to the Redirection Puzzle</title>
		<link>http://cosine.org/2007/09/27/answers-redirection-puzzle/</link>
		<comments>http://cosine.org/2007/09/27/answers-redirection-puzzle/#comments</comments>
		<pubDate>Thu, 27 Sep 2007 12:00:14 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/27/answers-redirection-puzzle/</guid>
		<description><![CDATA[This post discusses answers to the Redirection Puzzle.  Do not read on if you do not want to see or discuss answers (yet).  

My solution is not very complicated or long at 57 characters (9 of them spaces, 6 of them optional), but it is less than the ideal of the shell providing [...]]]></description>
			<content:encoded><![CDATA[<p>This post discusses answers to the <a href="/2007/09/27/redirection-puzzle">Redirection Puzzle</a>.  Do not read on if you do not want to see or discuss answers (yet). <img src='http://cosine.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-37"></span><!-- adman --></p>
<p>My solution is not very complicated or long at 57 characters (9 of them spaces, 6 of them optional), but it is less than the ideal of the shell providing better support for pipe redirection.  I would like to see <a href="http://zsh.sourceforge.net/">zsh</a> incorporate the Plan 9 redirection syntax to make this easier.  I would have suggested it to them, but I feel like such a suggestion should have a patch attached. <img src='http://cosine.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Anyway, go ahead and post answers or potential solutions to the puzzle below in the comments.  If you do not want to register for an account you can email your answers or questions to <b>cosine</b>&nbsp;at&nbsp;<b>cosine</b>&nbsp;dot&nbsp;<b>org</b>.  I will post noteworthy comments sent to my email below.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/27/answers-redirection-puzzle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redirection Puzzle</title>
		<link>http://cosine.org/2007/09/27/redirection-puzzle/</link>
		<comments>http://cosine.org/2007/09/27/redirection-puzzle/#comments</comments>
		<pubDate>Thu, 27 Sep 2007 11:59:37 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/27/redirection-puzzle/</guid>
		<description><![CDATA[Today&#8217;s entry here at cosine.org is a little Unix puzzle for everyone to work.  I came up with this seven years ago when I was first reading about the Plan 9 shell, rc.  Plan 9&#8217;s shell has a nifty little syntax for connecting a pipe from an arbitrary file descriptor of one process [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s entry here at <a href="/">cosine.org</a> is a little Unix puzzle for everyone to work.  I came up with this seven years ago when I was first reading about the Plan 9 shell, rc.  Plan 9&#8217;s shell has a nifty little syntax for connecting a pipe from an arbitrary file descriptor of one process to any file descriptor of another process when they are invoked at the command line together.  Using this syntax we can pipe standard error to a different process than we pipe standard output to:</p>
<pre>
; <b>{puzzle2000 | tee out.log} |[2] tee err.log</b>
This is standard output
This is standard error
; <b>cat out.log</b>
This is standard output
; <b>cat err.log</b>
This is standard error
</pre>
<p><!-- adman --></p>
<p>As seen above, the <a href="/ex/2007/09/27/redirection-test/puzzle2000">puzzle2000</a> script outputs two lines.  It outputs &#8220;<code>This is standard output</code>&#8221; to standard output and &#8220;<code>This is standard error</code>&#8221; to standard error.  The challenge is repeating the above Plan 9 shell functionality using the Bourne shell instead.  Back in 2000 it took me about two weeks of throwing ideas around to work out a solution.  This is non-trivial because the Bourne shell&#8217;s pipe syntax can only connect the pipe from standard output of the first process to standard input of the second.  So can you figure out how to extend this functionality?  Give it a try!</p>
<p><strong>Please do not post answers or spoilers in the comments of this post.</strong>  I have set up an <a href="/2007/09/27/answers-redirection-puzzle">additional post</a> to discuss possible answers and to avoid spoiling it for those that want to work out the challenge.  I have also provided a little bit of information about my own solution there, and will eventually update that post with the solution itself.  Feel free to post your answers in the comments there (do not read them if you do not want to be spoiled!).  Also, if you do not want to register for an account you can email your answers or questions to <b>cosine</b>&nbsp;at&nbsp;<b>cosine</b>&nbsp;dot&nbsp;<b>org</b>, and I will post them if they are good (that is, if they would contribute to a positive discussion) even if they are not correct.</p>
<p>Note that I will delete comments below if they are a spoiler or if they discuss possible answers, so please limit the discussion here to clarification about what the challenge is or other general comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/27/redirection-puzzle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mind the Arguments</title>
		<link>http://cosine.org/2007/09/22/mind-arguments/</link>
		<comments>http://cosine.org/2007/09/22/mind-arguments/#comments</comments>
		<pubDate>Sat, 22 Sep 2007 12:00:27 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/22/mind-arguments/</guid>
		<description><![CDATA[How command line arguments are processed in Unix is important to know when scripting.  That which should be a simple script is often troublesome to debug if the arguments to some of the commands get mangled unexpectedly.
To help understand what ends up being sent as command line arguments to a command, we can use [...]]]></description>
			<content:encoded><![CDATA[<p>How command line arguments are processed in Unix is important to know when scripting.  That which should be a simple script is often troublesome to debug if the arguments to some of the commands get mangled unexpectedly.</p>
<p>To help understand what ends up being sent as command line arguments to a command, we can use a little Perl script I wrote to see exactly what the arguments are and how they were broken up by the shell.  It does nothing more that print each argument out on a line of its own, but just that little service is enough to learn the finer points of command line argument processing.  I called this script <strong>sargs</strong>, and here is the code:</p>
<pre>
#!/usr/bin/env perl
foreach $arg (@ARGV) {
  print(&#34;$arg&#92;n&#34;);
}
</pre>
<p>Let us take a look at it in action in a few different circumstances.  First with three arguments:</p>
<pre>
% <b>sargs 1 2 3</b>
1
2
3
</pre>
<p>Now with the same three arguments combined as one:</p>
<pre>
% <b>sargs &#39;1 2 3&#39;</b>
1 2 3
</pre>
<p>We all know that quoting an argument allows us to put spaces and other special characters within them, and with sargs we can see it first hand.  With one more simple example, let us see shell wildcards in action:</p>
<pre>
% <b>sargs /*</b>
/bin
/boot
/cdrom
/dev
/etc
/home
/lib
/lost+found
/mnt
/opt
/proc
/root
/sbin
/service
/sys
/tmp
/usr
/var
</pre>
<p>This is the evidence that it is the shell, not the command, that interprets the wildcard asterisk (*) and expands it into many arguments, one for each file with a matching name.</p>
<p>Now let us use sargs for something more useful.  What happens to command line arguments in a command issued with SSH?  SSH mangles the command line when used to issue shell commands.  How?  We can see exactly how.  Three arguments apart are seen as normal:</p>
<pre>
% <b>ssh localhost sargs 1 2 3</b>
1
2
3
</pre>
<p>But if I group them inside quotes, something does not work right:</p>
<pre>
% <b>ssh localhost sargs &#39;1 2 3&#39;</b>
1
2
3
</pre>
<p>Those were supposed to be one argument!  What SSH does is it joins all the command line arguments it receives and passes the string to a shell for interpretation, which in this case includes parsing the one argument as separate arguments.  Thus, to keep those arguments together we need to make sure that the quotes are seen by SSH by escaping them:</p>
<pre>
% <b>ssh localhost sargs &#34;&#39;1 2 3&#39;&#34;</b>
1 2 3
</pre>
<p>That is what we wanted.  Since SSH joins all the arguments together, we can even send them to SSH as separate arguments as long as the quotes are escaped:</p>
<pre>
% <b>ssh localhost sargs &#92;&#39;1 2 3&#92;&#39;</b>
1 2 3
</pre>
<p>So next time you have trouble with running commands over SSH remember that the shell gets to see the SSH command and run it and that it is not run directly by the sshd process.  Let us take a quick look at sudo to see if it behaves similarly:</p>
<pre>
% <b>sudo sargs &#39;1 2 3&#39;</b>
1 2 3
</pre>
<p>There is no reprocessing by the shell here.  This is good most of the time when you want to run sudo for a single command because there are no shell double-interpreting surprises.  This is bad if you want to run two commands with one invocation of sudo, like this:</p>
<pre>
% <b>sudo sargs 1 2 &#39;&amp;&amp;&#39; sargs 3 4</b>
1
2
&amp;&amp;
sargs
3
4
</pre>
<p>Oops!  That second command got processed as arguments of the first!  Normally it is recommended that you invoke sudo twice and not quote the double-ampersand like so:</p>
<pre>
% <b>sudo sargs 1 2 &amp;&amp; sudo sargs 3 4</b>
1
2
3
4
</pre>
<p><!-- adman --></p>
<p>But sometimes you cannot do that, such as if the first command is <code>sleep</code> and you cannot allow the second sudo command to request your password again because you will be at lunch (<code>sleep 900; shutdown -r now</code>).  Sure, you could use <code>at</code>, but that can be messy in its own way for some tasks.  So how can we invoke sudo so that it can run two commands?</p>
<p>The answer is you cannot, but you can invoke sudo to run a command that runs two commands.  What command might that be?  A shell invoked as a command, of course!  All of the shells that I know of use the -c flag for this.  If you provide a -c flag, the next argument is expanded as a shell command and you can use the special shell characters to break the command up into multiple commands:</p>
<pre>
% <b>sudo zsh -c &#39;sargs 1 2 &amp;&amp; sargs 3 4&#39;</b>
1
2
3
4
</pre>
<p>It is not as pretty as one might hope, but it is reasonably easy to do.</p>
<p>I hope that if you had trouble in the past with figuring out how arguments are handled by different programs that you take this chance to learn using sargs.  It can really come in handy some day when you are programming that script that you need &#8220;an hour ago&#8221; but cannot quite figure out why it does not work right.  If that happens to you, just whip out sargs and verify that your commands are seeing their arguments exactly as they are supposed to see them, and if not then escape or unescape the offending special characters appropriately!</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/22/mind-arguments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scrutinizing SSH</title>
		<link>http://cosine.org/2007/09/18/scrutinizing-ssh/</link>
		<comments>http://cosine.org/2007/09/18/scrutinizing-ssh/#comments</comments>
		<pubDate>Tue, 18 Sep 2007 12:00:15 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/18/scrutinizing-ssh/</guid>
		<description><![CDATA[In my previous post titled Bolting on Security, I mentioned that port 22 is generally not scrutinized as much as 445 when being allowed through a firewall.  Obviously the situation varies from incident to incident, but I wanted to say that port 22 really should be looked at more closely.  All is not [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.cosine.org/2007/09/14/bolting-security/">previous post titled Bolting on Security</a>, I mentioned that port 22 is generally not scrutinized as much as 445 when being allowed through a firewall.  Obviously the situation varies from incident to incident, but I wanted to say that port 22 really should be looked at more closely.  All is not always roses and peaches when you allow port 22, but I am going to explain some of the saving graces of SSH that can make it less threatening in some hairy situations.</p>
<p><b>The Threats</b></p>
<p>Let us first start with what is wrong with allowing SSH through a firewall.  Then we will address each problem one by one.  The problems are:</p>
<ol>
<li>Buffer overflow bugs have led to system compromise.</li>
<li>Shell access can often be obtained when none is necessary.</li>
<li>SSH supports weak forms of authentication&mdash;like passwords.</li>
<li>SSH allows the forwarding of connections between the client and the server.</li>
<li>SSH helps facilitate X11 forwarding, allowing graphical programs to run remotely.</li>
</ol>
<p><b>Buffer Overflows</b></p>
<p>This is your greatest threat to giving up root access to your server, but fortunately there is something you can do to reduce the risk of break-in to negligible levels.  That something is to turn on <em>privilege separation</em>.  The only SSH daemon that supports privilege separation is <a href="http://www.openssh.com/">OpenSSH</a> and its more recent derivatives.  Fortunately, OpenSSH is a full featured SSH server so even if you are not using it, you should be able to switch to it without much difficulty.</p>
<p><!-- adman --></p>
<p>Note that despite Sun SSH being a derivative of OpenSSH, Sun has chosen not to implement privilege separation and thus you would need to replace it.  I have badgered people at Sun about this.  I can tell you they had a reasonable excuse for omitting it from Solaris 9, but they really dropped the ball with Solaris 10.  I hope they can do better for Solaris 11.  Your mileage may vary on other operating systems, but the free ones generally use OpenSSH by default.</p>
<p>The reason privilege separation is so good is that it causes the majority of the SSH server code to run with no privileges in a chrooted jail.  The little bit of SSH that runs with full root privilege is scrutinized much more closely by the OpenBSD team and security researchers, so it is considered very safe.  I do not know of any exploitable vulnerabilities ever found in the privileged code after OpenSSH introduced privilege separation a few years ago (though I may have missed one).</p>
<p>To activate it, create an sshd user (the unprivileged account) and a /var/empty directory (the jail).  Then set the <code>UsePrivilegeSeparation</code> option to &#8220;yes&#8221; in sshd_config and restart your server.  You can test if privilege separation is active by looking at your process list after you connect.  When privilege separation is in use there will always be two extra processes for each SSH connection, one privileged owned by root, and one unprivileged owned by a regular account (authenticated user) or the sshd account (unauthenticated user).  Without privilege separation there is always just one extra process per connection.</p>
<p>Since you need to be using OpenSSH or a derivative to use privilege separation, I will assume you are using it for the rest of this post.</p>
<p><b>Shell Access When None is Necessary</b></p>
<p>Sometimes you only want to give someone the ability to transfer files via SCP or SFTP, two protocols that use SSH.  Traditionally you have to give full access to a shell to allow only file transfers with SSH.</p>
<p>One solution that has been around for quite some time is a program called <a href="http://sublimation.org/scponly/wiki/index.php/Main_Page">scponly</a>.  You use scponly as the default shell for &#8220;file transfer only&#8221; accounts, and it disallows command line and command access.  This program has previously had a few security problems that has occasionally allowed an authenticated user to &#8220;break out&#8221; into a shell, but overall has been very good.  The maintainers take its security seriously.</p>
<p><b>Password Authentication</b></p>
<p>Password authentication is great if you&mdash;oh who am I kidding!?  Password authentication is bad, and if you are trying to keep things apart by a firewall and there is a good chance that an attacker will start trying out passwords against your open port, then you better have something better than password authentication protecting the accounts.</p>
<p>SSH can be configured to disallow password authentication and require stronger credentials.  Just set the <code>PasswordAuthentication</code> option to &#8220;no&#8221; and those pesky little weak passwords will not be a problem.  Of course you will need to set up something else, such as SSH keys, Kerberos, or a challenge-response mechanism.  If you are in a high-security situation, you should consider using some form of two-factor authentication.</p>
<p><b>Support for Forwarding Connections</b></p>
<p>SSH can be used to forward connections, effectively bridging two networks to a limited extent.  If you are scrutinizing the security of an SSH server on the other side of a firewall, you will want to turn this off.  Do so by setting <code>AllowTcpForwarding</code> to &#8220;no&#8221;.</p>
<p>However, perhaps there is one port in particular that you do want to forward with SSH through your firewall.  This could be used to encrypt an insecure channel as it travels over an untrusted network, or it can allow an &#8220;outsider&#8221; to connect to a service inside your firewall.  Whatever the reason, you have a means of limiting what is allowed through at the server side.  This is done with the <code>PermitOpen</code> option on newer versions of OpenSSH&mdash;it can be used to limit what target systems and ports the server allows clients to forward to.  Even if you have full control of the client system, it always helps to add a layer of security on the server side, too.</p>
<p><b>Support for Forwarding X11 Displays</b></p>
<p>When it was released in the mid-90s, one of the biggest problems facing Unix users was how to run their X11 graphical applications securely.  The security of an X program was usually dependent on weak host-level security, and as a result anyone with a login on the system with the X client (the program) could also run an X client to snoop or annoy the user.  There was also a cookie-based authentication available, but it was difficult to teach users how to use it.</p>
<p>Along came SSH, and not only did it replace Telnet by providing a secure shell connection, it also provided a means to automatically configure the cookie-based authentication for X11 <em>and</em> forwarded the traffic over the encrypted channel.  Good for you when connecting to your company server internally.  Bad for you when you do not fully trust a user or an account that needs access to the system through a firewall.</p>
<p>This one is easy to disable, too.  Just set the <code>X11Forwarding</code> option to &#8220;no&#8221;.</p>
<p><b>Summary</b></p>
<p>Do not be afraid to allow SSH through your firewall, but take reasonable precautions and know your SSH server.  Know how to disable the features you do not need.  Get the SSH client to use the strongest form of authentication available.  Read the man pages for ssh_config and sshd_config and be familiar with many of their options.  Someday, when you need to boost the security of a connection somewhere, you will be glad you did.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/18/scrutinizing-ssh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yes</title>
		<link>http://cosine.org/2007/09/11/yes/</link>
		<comments>http://cosine.org/2007/09/11/yes/#comments</comments>
		<pubDate>Tue, 11 Sep 2007 12:00:56 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/11/yes/</guid>
		<description><![CDATA[I was talking with one of my Unix administrator friends yesterday that had never heard of /usr/bin/yes before.  I have to admit I was a little surprised at first, but when you think about it, /usr/bin/yes is hardly ever used these days.  To a younger administrator used to having a -y or -f [...]]]></description>
			<content:encoded><![CDATA[<p>I was talking with one of my Unix administrator friends yesterday that had never heard of /usr/bin/yes before.  I have to admit I was a little surprised at first, but when you think about it, /usr/bin/yes is hardly ever used these days.  To a younger administrator used to having a <code>-y</code> or <code>-f</code> flag on commands that cause an &#8220;always answer yes&#8221; or &#8220;force the action&#8221; effect, why would one ever need a command like /usr/bin/yes?</p>
<p>For those that have never heard of /usr/bin/yes, it repeatedly outputs the letter &#8216;y&#8217; followed by a newline.  It used to be used to answer &#8216;y&#8217; to questions posed by programs asking things like &#8220;should I proceed?&#8221; and &#8220;are you sure?&#8221;  If such commands do not have a mode to force them to be non-interactive and you want them to just perform the task without question, /usr/bin/yes is your tool.  Run &#8216;yes&#8217; and pipe the output to the interrogative command!  As always, be careful to not run something that could cause unknown harm when using this technique!</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/11/yes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving Up on Mini-Scripting</title>
		<link>http://cosine.org/2007/09/10/miniscripting/</link>
		<comments>http://cosine.org/2007/09/10/miniscripting/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 12:00:37 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/10/miniscripting/</guid>
		<description><![CDATA[After my previous post on ad hoc scripting I had an example come up in my own work.  I needed to search through some web logs for all hits in August to three servers from a pair of IP addresses.  Below is the actual command line script I used, except I changed some [...]]]></description>
			<content:encoded><![CDATA[<p>After my <a href="http://www.cosine.org/2007/09/05/scripting-command-line/">previous post on ad hoc scripting</a> I had an example come up in my own work.  I needed to search through some web logs for all hits in August to three servers from a pair of IP addresses.  Below is the actual command line script I used, except I changed some identifying information and extended the script from a single line to multiple lines for clarity.  This script reduced the logs to a file that details which web server was it, which IP address the request came from, and the date and time of the request:</p>
<pre>
let D=1; while (( D <= 31 )); do
  DD=$(printf "%02d" $D)
  for M in server-01 server-02 server-03 ; do
    gzip -cd $M/weblog.200708$DD.gz | \\
        perl -anle 'print "'$M' $F[0] $F[3]"
            if $F[0] =~ /^10\.1\.2\.[34]$/'
  done
  let D=D+1
done > ~/log_report
</pre>
<p>There are a few things I want to point out about this mini-script:</p>
<ol>
<li>Iteration is performed on an index value (<code>$D</code>), tested using Kornshell&#8217;s double parentheses syntax, and incremented using a <code>let</code> statement.</li>
<li>It makes use of a Perl one-liner to rearrange the data on each line and only print that data that is relevant to the task at hand.</li>
<li>I send the output of the entire thing to a file by redirecting it after the final &#8220;<code>done</code>&#8221; statement.</li>
</ol>
<p>None of these things is really a big deal to me anymore, but I have noticed many people do not think or know you can do these things.  I think that if you do realize it then you can come up with some more powerful mini-scripts from your command line.</p>
<p>I noted before that I use the <a href="http://zsh.sourceforge.net/">Z shell</a>, a Bourne compatible shell.  While the above mini-script will not work in the Bourne shell itself, it should also work in the Kornshell and the Bourne Again shell, though your mileage may vary.</p>
<p><b>Incrementing an Index</b></p>
<p>The generic script code for iterating over an increasing numeric index is:</p>
<pre>
let I=0; while (( I < 10 )); do
  ... <em>your code here</em> ...
  let I=I+1
done
</pre>
<p>If your shell is a traditional Bourne shell that does not support let-statements and double parentheses notation, then you may do this:</p>
<pre>
I=0; while [ $I -lt 10 ]; do
  ... <em>your code here</em> ...
  I=`echo $I + 1 | bc`
done
</pre>
<p>If you have a small set of numbers to iterate over then it is often still faster to just type them all out in a for-statement, but that stops being true when you have a large set of numbers.</p>
<p><!-- adman --></p>
<p><b>Invoking Perl and/or Ruby</b></p>
<p>This technique should not be alien to someone that writes shell scripts.  Even if you never thought to invoke Perl and/or Ruby in your scripts, you have probably used sed and awk.  In the above example I could have used awk instead of Perl, but Perl seemed like a better choice at the time.  Ruby and Perl have flags that help them be more useful on the command line, and in fact they can both become more powerful replacements for sed and awk.  Some flags are:</p>
<p><code><b>-n</b></code>: I call this the awk-mode flag.  It causes both Ruby and Perl to loop on each line of the input, putting that line of input into <code>$_</code>.</p>
<p><code><b>-p</b></code>: I call this the sed-mode flag.  It causes both Ruby and Perl to loop on each line of input like <code>-n</code>, but also prints the value of <code>$_</code> at the end of the loop (presumibly you have modified it).</p>
<p><code><b>-a</b></code>: This is often used with <code>-n</code>, though it could also be used with <code>-p</code>.  As each line of input is read, it is split and the resulting array stored in @F (Perl) or $F (Ruby).  I used this feature in the above mini-script to limit which fields are output to the report I generated.</p>
<p><code><b>-l</b></code>: This flag causes lines output to be terminated with a newline.  It also causes lines of data input via <code>-n</code> and <code>-p</code> to be auto-chomped.</p>
<p><code><b>-e</b></code>: The most important flag for one-liners!  This causes Perl and Ruby to take their commands from the argument given after <code>-e</code>.  It may be specified multiple times to issue more code from the command line.</p>
<p><code><b>-i</b></code>: If you want to edit a file in-place you can use this flag to tell Perl or Ruby to edit each file of input instead of leaving those files untouched.  You can also opt to provide an extension to be used for a backup of the input.  Note that because of the syntax for the optional extension use, you should check the man page for usage.</p>
<p><b>Redirecting Output</b></p>
<p>You can redirect output from any part of a script.  Most people focus on redirection of individual commands, but that causes one to have to keep appending data to an output file.  One does not need to do that!  Just redirect your output after the &#8220;<code>done</code>&#8221; and you will capture all of the output from all of the commands inside the loop.  Spiffy, eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/10/miniscripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scripting From the Command Line</title>
		<link>http://cosine.org/2007/09/05/scripting-command-line/</link>
		<comments>http://cosine.org/2007/09/05/scripting-command-line/#comments</comments>
		<pubDate>Wed, 05 Sep 2007 12:00:45 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/09/05/scripting-command-line/</guid>
		<description><![CDATA[One of the techniques I use to be effective at Unix systems administration is scripting from the command line.  If you understand Bourne shell&#8217;s for-loops and while statements, it is just one small step from only using them inside scripts to using them on the command line as part of an ad hoc mini-script. [...]]]></description>
			<content:encoded><![CDATA[<p>One of the techniques I use to be effective at Unix systems administration is scripting from the command line.  If you understand Bourne shell&#8217;s for-loops and while statements, it is just one small step from only using them inside scripts to using them on the command line as part of an ad hoc mini-script.  It makes sense, does it not?  We use shells for both scripting and command line interaction all the time, and if you do both a lot you should notice that they use the same syntax.</p>
<p>Note that I use the <a href="http://zsh.sourceforge.net/">Z Shell (zsh)</a>, which is a Bourne compatible shell.  These examples should also work in the Bourne shell (sh), the Kornshell (ksh), and the Bourne Again shell (bash).  They will <em>not</em> work in the C Shell (csh) or the Tenex C Shell (tcsh).  Those shells use a different syntax to accomplish the same thing.</p>
<p>If you want to run a program on one remote computer, you can with ssh like so:</p>
<pre>
workstation% <b>ssh server-01 /usr/local/bin/locate ruby</b>
</pre>
<p>Now you want to run the same thing on ten hosts (or twenty-five, or perhaps hundreds).  You could start by listing them all in a for-loop (note that the ellipses below are not literal&mdash;substitute those with the actual system names):</p>
<pre>
workstation% <b>for M in server-01 server-02</b> ... <b>server-10; do</b>
workstation for% <b>ssh $M /usr/local/bin/locate ruby</b>
workstation for% <b>done</b>
</pre>
<p>And there you go, and all done from the command line!  You can build things up even higher.  Now let us say you put your hosts into a file called HOSTLIST:</p>
<pre>
workstation% <b>for M in `cat HOSTLIST`; do</b>
workstation for% <b>ssh $M /usr/local/bin/locate ruby</b>
workstation for% <b>done</b>
</pre>
<p>You can add more logic in the middle of your loop.  This mini-script generates a list of systems that do not have their Ruby installed at a particular location:</p>
<pre>
workstation% <b>for M in `cat HOSTLIST`; do</b>
workstation for% <b>LOCATION=`ssh $M /usr/local/bin/locate ruby`</b>
workstation for% <b>if [ $LOCATION != /usr/local/bin/ruby ]; then</b>
workstation for if% <b>echo "$M: Ruby at non-standard location: $LOCATION"</b>
workstation for if% <b>fi</b>
workstation for% <b>done</b>
</pre>
<p><!-- adman --></p>
<p>Somewhere along the line here you might decide to move this script into a file of its own, but that is up to you to decide.  Whether or not I do so depends on how likely it is that I will use the ad hoc script again and how long it is.  In the example above, how often do you need to check that a particular program is at a particular path?  For me it is not very often, so I end up doing it with this kind of mini-script.  Perhaps you are always checking paths as part of regular audits, though, and thus would move the script to its own file to make it available for repeated use.  You will figure out the right thing to do in your environment. <img src='http://cosine.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/09/05/scripting-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debugging Connectivity Problems</title>
		<link>http://cosine.org/2007/08/21/debugging-connectivity-problems/</link>
		<comments>http://cosine.org/2007/08/21/debugging-connectivity-problems/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 12:00:27 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/08/21/debugging-connectivity-problems/</guid>
		<description><![CDATA[The Application is down!  No, wait!  Our Unix administrators just checked the server and it is running.  They swear by it, and say it is the network team&#8217;s equipment dropping packets.  The network team checks their systems and swear they are passing the traffic, and it must be an application configuration [...]]]></description>
			<content:encoded><![CDATA[<p>The Application is down!  No, wait!  Our Unix administrators just checked the server and it is running.  They swear by it, and say it is the network team&#8217;s equipment dropping packets.  The network team checks their systems and swear they are passing the traffic, and it must be an application configuration issue.  The application folks, who originally reported the problem, throw up their hands and go back to the systems administrators for more help.  Before long the teams are in a quagmire of blame and nothing is getting done towards fixing the issue.  How can we step around that?  What should we be doing to fix the Application?  If you are the systems administrator then let us try and verify what the network guys are saying.  If they really are dropping packets then let us bring some confirmation of that to the table.</p>
<p>Firstly, check your routing tables and your basic network configuration.  More than one Unix administrator on a rampage of righteous indignation against their network team has found himself swallowing his own pride when it was discovered that he had errors in his routing table.  So check your IP address, your netmask, and your default router first.  All good?  Now check if you need or have any other routes in your routing table.  All good here, too?  Excellent!  If you are new to Unix and need help finding this information, read the man pages for ifconfig and netstat to get started.  I would love to give some examples but it differs very much from Unix variant to Unix variant.  In general, though, use &#8220;netstat -nr&#8221; for viewing the routing table and &#8220;ifconfig -a&#8221; for seeing all of the network interface configuration information.</p>
<p>Now that you IP configuration is confirmed, let us move on to the connection in question.  Firstly, you have to identify the port and protocol of the connection.  If you are running a standard protocol, such as HTTP, then you can likely assume port 80, but perhaps you do not know?  We have a couple options.</p>
<p><span id="more-24"></span>There are a myriad of tools to see what connections and proto-connections exist on the system.  I like <a href="ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/">lsof</a> because I can view the connections for each individual process.  So let us say I have that HTTP server I mentioned above running on my Unix server, but I am not sure if it is running on port 80 or some other port.  I can start the web server process, note what its process ID is with ps, and then use lsof to view its listening sockets to see what port the clients should connect to.</p>
<p>I am using Mac OS X today, which has a BSD style ps command:</p>
<pre>
% <b>ps auxw | grep httpd</b>
root     13888   0.0 -0.3    41732   5348  ??  Ss   Tue05PM   0:15.24 /usr/sbin/httpd
www      14549   0.0 -0.0    32636    796  ??  S    Wed09AM   0:00.00 /usr/sbin/httpd
</pre>
<p>When using a System V style ps I use &#8220;ps -ef&#8221; instead of &#8220;ps auxw&#8221;.  The process ID here for httpd is 13888 (I could also use 14549 because they share the port, in a sense, but that may not always be the case).  So let us run lsof to see what ports are open:</p>
<pre>
% <b>sudo lsof -Pnp 13888 | egrep &#39;TCP|UDP&#39;</b>
httpd   13888 root   16u    IPv4 0x76fe710      0t0       TCP *:80 (LISTEN)
</pre>
<p>It <em>is</em> port 80!  And in particular it is <em>TCP</em> port 80.  Note that this is opposed to <em>UDP</em> port 80, which is another beast altogether that we will address below.  For now let us move on to testing this connection.</p>
<p><b>Testing TCP Connectivity</b></p>
<p>The most widespread tool for checking if there is a firewall between two systems blocking a particular TCP port is telnet.  It is not the best utility, but it does the job and is ubiquitous; you will find it on almost all Unix and Windows systems, and sometimes even VMS and mainframes.</p>
<p>To use telnet, just get to a command line and type &#8220;telnet&#8221; followed by the target system and port number:</p>
<p><code>telnet my-web-server.example.com 80</code></p>
<p>If all is well and you can reach the server, you should see something like this:</p>
<pre>
% <b>telnet my-web-server.example.com 80</b>
Trying 192.168.1.10...
Connected to my-web-server.example.com.
Escape character is &#39;^]&#39;.
</pre>
<p>If the service is down, but there is no firewall intervention, you will see something along the lines of &#8220;connection refused&#8221; like below:</p>
<pre>
% <b>telnet my-web-server.example.com 80</b>
Trying 192.168.1.10...
telnet: connect to address 192.168.1.10: Connection refused
telnet: Unable to connect to remote host
</pre>
<p>But what if there is a firewall in between dropping all the packets?  You would see the message attempting to make the connection, and then telnet will seem to just freeze for many seconds.  After some time it will report a failure, but if you see it freezing for more than ten seconds then you can terminate the connection attempt with control-C.  Here is what it looks like:</p>
<pre>
% <b>telnet my-web-server.example.com 80</b>
Trying 192.168.1.10...
<em>(At this point telnet will stop and wait for a few minutes.)</em>
telnet: connect to address 192.168.1.10: Operation timed out
</pre>
<p>Note that even if it looks like a firewall is dropping the packets, there may be any number of other causes:</p>
<ol>
<li>Host-based firewall on source host blocking outbound traffic.</li>
<li>Host-based firewall on destination host blocking inbound traffic.</li>
<li>Target host is down.</li>
<li>Either host has an error in its routing table.</li>
</ol>
<p><b>Testing UDP Connectivity</b></p>
<p><!-- adman --></p>
<p>Sometimes applications use UDP instead of TCP for their communications.  This can be tricky to handle if trying to determine if you have a network issue between nodes.  The reason is that UDP does not require the other host to reply; if you send a packet that is received you see the same thing as if you send a packet that never reaches its destination.  Note that if you send a UDP packet that arrives to a system <em>not</em> accepting packets then you do get a different behavior that you can measure, because in that case the system will notify you that it is not accepting packets there.</p>
<p>So first make a little extra effort to ensure both hosts are up and that the routing table works between them.  You can do this by probing any TCP port (open or closed) or with an ICMP ping.  As long as <em>those</em> packets can get through you know your routing tables are okay (note this does not rule out host-based firewalls as a problem as specific ports may be filtered).</p>
<p>We can try to send a generic packet to the other host with either ping or traceroute&mdash;those two are widely available&mdash;or netcat if you have it.  Netcat is the best if it is available:</p>
<pre>
% <b>nc -vvuz my-cifs-server.example.com 137</b>
my-cifs-server.example.com [192.168.1.20] 137 (netbios-ns) open
 sent 0, rcvd 0
</pre>
<p>The means of getting ping or traceroute to send a single UDP packet to a specific port varies per system and is even impossible in some (all?) versions of Windows.  Because of these differences, I recommend installing netcat and using it if you need to debug UDP connections (it is also better than telnet for debugging TCP connections).</p>
<p>Since we really only know that we do not have a network issue if the port shows up as &#8220;closed&#8221; we have to do more research to confirm a network problem.  Note that if you have the luxury of being able to shutdown the UDP service on the destination host then you should do so for testing so you can observe the closed state.</p>
<p>The next tool you need to fully debug a broken UDP connection is a packet sniffer.  I recommend <a href="http://www.wireshark.org/">Wireshark</a> if you are on Windows, or <a href="http://www.tcpdump.org/">tcpdump</a> if you are on any non-Solaris Unix system.  On Solaris, use the built-in &#8220;snoop&#8221; command.  Each of these has a somewhat different usage:</p>
<p><code>tcpdump -i en1 &#39;host my-cifs-server.example.com and udp and port 137&#39;</code><br /> <code>snoop -d ce0 &#39;host my-cifs-server.example.com and udp and port 137&#39;</code><br /> Wireshark is usually run in a GUI, particularly on Windows.</p>
<p>Get your packet sniffer running and start talking to your port.  If you do not see your packets going out, you are doing something wrong.  Go back and figure out if you are sniffing the wrong interface or have an error in your usage.  If you do see your packets going out but none returning, then it is still inconclusive, but at least you know you are sniffing the right thing.  If you do see return packets, your connection is open and you can proceed with troubleshooting your application instead of the network.</p>
<p>The key here is to get the other server to send packets back in response to packets sent.  If you can do that then you know the connection works.  Unfortunately, many servers just ignore stuff they consider garbage, like the packets we were sending with netcat.</p>
<p>In our case, we are trying to connect to a NetBIOS name service running on UDP port 137.  Some such servers reply to garbage with garbage (success for us!) and some just drop the packets, leaving us confused.  To get these guys stirred up we need to generate some real NetBIOS name service traffic from our workstations or servers.  In this case, we would log into our Windows workstation and try to connect to a file share on the server; we could also run the nbtstat command instead.  In either case, with our sniffer armed and ready we will hope it is enough to generate a reply.  If there is truly a NetBIOS name service running on the remote port, we should see evidence of it in the sniffer output.  If not, then it is at this point that we can turn towards the network and in good conscience assume all is well from the server side (because you did check your host-based firewall settings, right?).</p>
<p>Debugging network connectivity issues does not have to be a nightmare.  With the right tools, knowledge, and experience doing so you can be a pro at determining if an issue needs resolution in your application, on the OS it is running on, or the network.  Be the hero that <em>knows</em> instead of guesses what is happening out there, because the resolution often follows.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/08/21/debugging-connectivity-problems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Secure FTP in All its Forms</title>
		<link>http://cosine.org/2007/08/18/secure-ftp-forms/</link>
		<comments>http://cosine.org/2007/08/18/secure-ftp-forms/#comments</comments>
		<pubDate>Sat, 18 Aug 2007 12:00:32 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/08/18/secure-ftp-forms/</guid>
		<description><![CDATA[It is the File Transfer Protocol.  FTP has been an important part of the Internet for more than 20 years.  Businesses depend on it to transfer data from system to system and from business to business.  In today&#8217;s world of SOX, HIPPA, PCI, and other standards and regulations companies are not only [...]]]></description>
			<content:encoded><![CDATA[<p>It is the File Transfer Protocol.  FTP has been an important part of the Internet for more than 20 years.  Businesses depend on it to transfer data from system to system and from business to business.  In today&#8217;s world of SOX, HIPPA, PCI, and other standards and regulations companies are not only required to get the data moved, but to move it securely.  &#8220;We need secure FTP,&#8221; cry the business units.</p>
<p>However, in the rush to address the needs to secure file transmissions we ended up with multiple protocols.  And even among those protocols there are multiple standards regarding how to operate them.  To connect a client to a server both sides have to select the same technology, and simply saying &#8220;we want/do secure FTP&#8221; just leaves implementors in a quandary about <em>which kind</em> of secure FTP.</p>
<p><span id="more-22"></span><b>SFTP &mdash; FTP over SSH</b></p>
<p>SFTP (S <em>before</em> FTP) is the protocol that describes an FTP-like protocol that is secured over an SSH channel.  SSH&#8217;s standard port is 22, and so SFTP&#8217;s standard port is also 22.  SFTP is very &#8220;firewall friendly&#8221; because all communications run over a single connection.  On the down side, most implementations of SFTP carry with them a full implementation of SSH, and SSH is traditionally used for shell access.  For a typical business connection, allowing shell access is highly undesirable.  The most recent versions of SSH servers are beginning to realize an &#8220;SFTP only&#8221; configuration is a good feature to support, so this situation is fast improving.</p>
<p><b>FTPS &mdash; FTP over SSL</b></p>
<p>FTPS (S <em>after</em> FTP) is a different protocol entirely.  FTPS is a super-set of the same FTP protocol that the Internet has relied upon for years and years, but it allows for encryption of the connection over an SSL or TLS encrypted socket.  This protocol is harder to allow through firewalls because it follows the same process of opening additional connections from server to client or from client to server as the unencrypted version of the FTP protocol.</p>
<p><b>Implicit FTPS</b></p>
<p>To further complicate things a little, the FTPS protocol can be run in an &#8220;implicit&#8221; mode or an &#8220;explicit&#8221; mode.  The implicit mode was used originally; it is an SSL encrypting socket wrapped around the entire communication starting at the point of initial connection.  To differentiate this original FTPS from unencrypted FTP, the encrypted FTPS was assigned a standard port of 990.  If you see an FTPS server running on port 990, that is almost certainly an implicit FTPS server.  It is called &#8220;implicit&#8221; because the directive to encrypt the connection is implied by using port 990.  Note that this mode is far less common than the explicit mode.</p>
<p><b>Explicit FTPS</b></p>
<p>Soon after FTPS was in use some smart people decided it would be best if we could have an FTP server that could support unencrypted as well as encrypted connections, and do it all over the same port.  To accommodate this the &#8220;explicit&#8221; FTPS protocol connection begins as a normal unencrypted FTP session over FTP&#8217;s standard port 21.  The client then explicitly informs the server that it wants to encrypt the connection by sending an &#8220;AUTH TLS&#8221; command to the server.  At that point the FTPS-enabled server and the client begin the SSL or TLS handshake and further communications happen encrypted.  Note that most (if not all) explicit FTPS servers can be optionally configured to <em>require</em> encryption, so it will deny clients that attempt to transfer data unencrypted.  Often this can be configured on a user by user basis.</p>
<p>Of these three &#8220;secure FTP&#8221; protocols, only explicit FTPS is defined by an RFC.  In this case it is <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a>, released in 2005, even though all these protocols had been in use for years prior.</p>
<p>By the way, I have not discussed what encryption algorithms each of these modes use.  They all can use AES if you want, and they often have other good options, too.  Do not worry about the algorithm when simply selecting which protocol to use; they are all good from this standpoint.</p>
<p><b>Comparison</b></p>
<p>Which kind of secure FTP should you use?  It really depends on your business, software availability, and network firewall situation.  I personally have no preference for or against any of these protocols on their base merits.  Here is a table recapping some of the differences:</p>
<table border="1">
<tr>
<th>Secure FTP Type</th>
<th>SFTP</th>
<th>Explicit FTPS</th>
<th>Implicit FTPS</th>
</tr>
<tr>
<th>Encryption by</th>
<td>SSH</td>
<td>SSL or TLS</td>
<td>SSL or TLS</td>
</tr>
<tr>
<th>Common Authentication Options</th>
<td>password, SSH key pair, hosts-based authentication,<br />
      GSSAPI (Kerberos and Active Directory)</td>
<td>password, SSL certificate</td>
<td>password, SSL certificate</td>
</tr>
<tr>
<th>Default Port</th>
<td>22</td>
<td>21 and more for data connections</td>
<td>990 and more for data connections</td>
</tr>
<tr>
<th>Firewall Implications</th>
<td>easy; just allow 22</td>
<td>difficult; see below</td>
<td>difficult; see below</td>
</tr>
<tr>
<th>Additional Host Security Implications</th>
<td>might allow access to shell (possibly undesired)</td>
<td>none</td>
<td>none</td>
</tr>
<tr>
<th>Availability of Software</th>
<td>common, comes with many SSH and FTP packages</td>
<td>common, comes with most FTP packages</td>
<td>uncommon</td>
</tr>
</table>
<p><b>Firewall Implications</b></p>
<p><!-- adman --></p>
<p>I have been mentioning some firewall implications for the FTP over SSL variants, but let us go into more detail.  The FTP protocol initially opens one connection to authenticate the user and for the user to issue commands to the server.  This is all well and good until the user wants to view the contents of a directory or transfer a file.  Once either of those activities are requested, there is another connection made.  To make things even more fun, the connection can be either from client to server (called <em>passive mode</em>) or from server to client (called <em>active mode</em>).  I will just simply call these passive and active data connections, respectively, based on the name of the mode of transfer.</p>
<p>When FTP is always unencrypted, firewalls have been using a little trick to allow the active and passive data connections.  They can snoop your connection and see what ports are being decided upon for these connections, and then they quickly allow the connection to get through once.  That option is not available when the connection is encrypted.  Thus, firewalls need another way to figure things out.</p>
<p>The active data connections (from server back to client) turn out to be relatively easy to firewall from the server side.  They always use port 20 (for explicit FTPS) or port 989 (for implicit FTPS) as the <em>source port</em> of the connection (this can be configured to be a different port in many servers).  A firewall protecting an FTPS server can just confirm that there exists at least one FTPS connection to that server, and assume that outbound connections with the right source port are okay.  Most firewalls just end up being configured to always allow these connections based on the source port, and that is usually okay, too.</p>
<p>The passive data connections, by default on most servers, could be anything inbound between 49152 and 65535 (or sometimes between 1024 and 65535, depending on OS and server).  Most organizations do not want to allow this many ports through the firewall to the server.  Fortunately, the better FTPS servers also allow this range to be configured.  Select a fixed range large enough to handle your traffic load and configure your FTPS server to only use that range for its passive ports.  Then allow those ports through the firewall in addition to the main connection at 21 or 990.</p>
<p>If you want to serve the greatest number of clients with your FTPS server, you will want to support both active and passive mode connections.  Some clients can figure out how to get one type but not the other through their firewalls.  You can never guess which one it will be, though passive mode is more likely because all they have to do is allow the connections <em>out</em> from their network.  If for some reason your organization decides to only support one mode and not the other, make sure your clients have some means of being notified!  Even better if you can configure your FTP server to simply deny an attempt to open data connections using the mode your firewalls do not permit.</p>
<p>Note that even if you are not using SFTP or FTPS, there are other means of securing FTP connections defined in <a href="http://www.ietf.org/rfc/rfc2228.txt">RFC 2228</a>.  Someone could, in theory, refer to a &#8220;secure FTP&#8221; connection that uses another means besides SSH or SSL to secure the connection via the extensions to the FTP protocol defined by that RFC.  In practice (excepting Kerberized FTP), I have seen <em>only</em> the types of secure FTP I described above.</p>
<p>I wrote this article to help you decide which type of secure FTP to use.  You need to know all these issues to make the best decision for your company:  SFTP versus FTPS, implicit versus explicit, and active versus passive.  Perhaps even more important is that you need to know how to correctly communicate your decisions to other technical implementers, and you need to understand the right questions to ask of others intending to implement (or already have implemented) &#8220;secure FTP&#8221; but who do not know about the differences between these forms.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/08/18/secure-ftp-forms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using RCS to Version Control Your Unix Host</title>
		<link>http://cosine.org/2007/08/14/rcs-version-control-unix-host/</link>
		<comments>http://cosine.org/2007/08/14/rcs-version-control-unix-host/#comments</comments>
		<pubDate>Tue, 14 Aug 2007 12:00:39 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/08/14/rcs-version-control-unix-host/</guid>
		<description><![CDATA[Ever make a change on that Unix host you manage and need to undo it?  Good thing you made a backup, right?  You even gave it an extra extension, .bak, so that you would know it was the backup.  But wait a minute, this file also has copies with extensions .backup, .20070813, [...]]]></description>
			<content:encoded><![CDATA[<p>Ever make a change on that Unix host you manage and need to undo it?  Good thing you made a backup, right?  You even gave it an extra extension, .bak, so that you would know it was the backup.  But wait a minute, this file also has copies with extensions .backup, .20070813, .20051221, and .john.  Do we need all these?  Looking through them, they seem like copies we can do without, but even so they still contain some interesting historical data.  And I really would feel funny about deleting the .john copy without asking John about it.  What to do?!  Simple, it is RCS to the rescue.</p>
<p><span id="more-19"></span>You can use RCS to version control your files.  RCS is able to keep a history of previous revisions, and it provides a log for people to note why they made their change.  Let us work through an example!  A common administrative file that can benefit from RCS is /etc/sudoers.  This file is not changed automatically and should only be altered by the Unix administrators.  Let us start with a basic sudoers file:</p>
<pre>
%unixadmins     ALL = (ALL) ALL
</pre>
<p>We want to add another line for our Oracle administrators, but we want to save the original copy of this file.  We first use RCS&#8217;s ci (check in) program to create the initial revision of the file:</p>
<pre>
i_am_root# <b>cd /etc</b>
i_am_root# <b>ci -l sudoers</b>
sudoers,v  &lt;--  sudoers
enter description, terminated with single &#39;.&#39; or end of file:
NOTE: This is NOT the log message!
&gt;&gt; <b>sudo uses this file to determine permissions</b>
&gt;&gt; <b>.</b>
initial revision: 1.1
done
</pre>
<p><!-- adman --></p>
<p>This creates the revision history file, sudoers,v, in the /etc directory right with the sudoers file.  If a directory named RCS exists, then the revision history file will be located there.  You can use a symbolic link named RCS to store your revision history files anywhere you want (I put all mine in a centralized location).</p>
<p>Creating your revision history file leaves the sudoers file in a &#8220;checked out&#8221; state.  This is necessary because creating the revision history file without also checking out the file will cause the original file to be deleted (oops).  Therefore, you may begin editing the file now, or you might want to just check it in so someone else can edit it, too.  The command to check files in, ci, can be used with the -u flag instead of -l to unlock the file instead of locking it:</p>
<pre>
i_am_root# <b>ci -u sudoers</b>
sudoers,v  &lt;--  sudoers
file is unchanged; reverting to previous revision 1.1
done
</pre>
<p>Let us check the file back out for editing now.  We use RCS&#8217;s co (check out) command to perform the task, and co takes -l as an option when locking is requested:</p>
<pre>
i_am_root# <b>co -l sudoers</b>
sudoers,v  --&gt;  sudoers
revision 1.1 (locked)
done
</pre>
<p>Now edit the file to add the permissions for the Oracle DBAs.  I do not care what your editor religion is as long as it is vi or emacs. <img src='http://cosine.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre>
%unixadmins     ALL = (ALL) ALL
%oracledbas     ALL = (oracle) ALL
</pre>
<p>We can use RCS&#8217;s rcsdiff command to see what we have changed:</p>
<pre>
i_am_root# <b>rcsdiff sudoers</b>
===================================================================
RCS file: sudoers,v
retrieving revision 1.1
diff -r1.1 sudoers
1a2
&gt; %oracledbas     ALL = (oracle) ALL
</pre>
<p>Beautiful!  It does not seem so useful for so small a change, but if you are making a lot of changes to a file then it is more useful.  You can also use rcsdiff to view differences between revisions, which is extremely useful if you are trying to figure out when a particular line in the file was introduced (e.g. <code>rcsdiff -r1.1 -r1.3 sudoers</code>).  If the standard diff format output is undesired, then try -c or -u (the latter not available on all systems) to change up the output format.  As with everything, read the man pages for more details.  If your man pages are lacking, use <a href="http://www.openbsd.org/cgi-bin/man.cgi">the man pages</a> at <a href="http://www.openbsd.org/">OpenBSD</a> because they are the best (they describe OpenRCS, an RCS clone, whereas most systems will have the official RCS; but the basic usage is the same).</p>
<p>We are not quite done, but we are almost there.  We have to check in our change.</p>
<pre>
i_am_root# <b>ci -u sudoers</b>
sudoers,v  &lt;--  sudoers
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single &#39;.&#39; or end of file:
&gt;&gt; <b>added permissions for Oracle DBAs</b>
&gt;&gt; <b>.</b>
done
</pre>
<p>There are other revision control programs out there, and some of them have their place, too, but RCS is still the best for <em>individual</em> system file revision control.  Also be careful in how you use it with ever-changing system files, such as /etc/passwd and /etc/shadow.  For files such as those a cron job taking a daily backup by using <code>ci -l</code> will suffice.  So get rid of all those extra backup files!  The only extra copy you ever need has a suffix of ,v.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/08/14/rcs-version-control-unix-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parsing Dates in Unix with Ruby</title>
		<link>http://cosine.org/2007/08/11/parsing-dates-unix-ruby/</link>
		<comments>http://cosine.org/2007/08/11/parsing-dates-unix-ruby/#comments</comments>
		<pubDate>Sat, 11 Aug 2007 06:48:32 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/08/11/parsing-dates-unix-ruby/</guid>
		<description><![CDATA[Ever need to write a script that can read a human readable date and turn it into something a computer can use?  How often do you have &#8220;August 10, 2007&#8243; in a string and need that converted to a number of seconds since January 1, 1970?
As it turns out, Ruby includes an excellent module [...]]]></description>
			<content:encoded><![CDATA[<p>Ever need to write a script that can read a human readable date and turn it into something a computer can use?  How often do you have &#8220;August 10, 2007&#8243; in a string and need that converted to a number of seconds since January 1, 1970?</p>
<p>As it turns out, Ruby includes an excellent module for parsing dates.  It can handle several common formats, too!  All you need to do is require &#8216;parsedate&#8217; and you have access to it:</p>
<p><span id="more-17"></span>(Text in bold is what <em>you</em> would type.)</p>
<pre>
require &#39;parsedate&#39;
user_input = ARGF.readline
seconds = Time.local(*ParseDate.parsedate(user_input)).to_i
puts seconds

% <b>ruby parsedate_example</b>
<b>August 10, 2007</b>
1186722000
</pre>
<p>If you are in a hurry, try a one-liner:</p>
<pre>
% <b>ruby -rparsedate -nle &#92;
      &#39;print Time.local(*ParseDate.parsedate($_)).to_i&#39;</b>
<b>August 10, 2007</b>
1186722000
<b>2006-09-21</b>
1158814800
<b>2001 sep 8</b>
999925200
</pre>
<p>If you deal with <code>/etc/shadow</code> a lot you will find this useful for figuring out what today is in terms of the password last changed field by dividing the given number by 86400 (the number of seconds in each day):</p>
<pre>
% <b>ruby -rparsedate -nle &#92;
      &#39;print Time.local(*ParseDate.parsedate($_)).to_i / 86400&#39;</b>
<b>August 10, 2007</b>
13735
</pre>
<p>Or do it in reverse with Time.at:</p>
<pre>
% <b>env TZ=GMT ruby -nle &#39;print Time.at($_.to_i * 86400)&#39;</b>
<b>13735</b>
Fri Aug 10 00:00:00 +0000 2007
</pre>
<p>With Ruby you never need to venture far to manage your dates!  Let me know if you find this useful or if you have questions about similar should-be-easy problems you encounter!</p>
<p><!-- adman --></p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/08/11/parsing-dates-unix-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capistrano and Administration</title>
		<link>http://cosine.org/2007/07/18/capistrano-administration/</link>
		<comments>http://cosine.org/2007/07/18/capistrano-administration/#comments</comments>
		<pubDate>Wed, 18 Jul 2007 23:00:41 +0000</pubDate>
		<dc:creator>Cosine Jeremiah</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.cosine.org/2007/07/18/capistrano-evolution/</guid>
		<description><![CDATA[Know what Capistrano is?  I did a presentation on it in February, so I know a little about it.  At the time I was investigating it as a hopeful candidate that could assist with configuration management for general systems administration for an environment of about 150 Solaris systems.  I discovered that Capistrano [...]]]></description>
			<content:encoded><![CDATA[<p>Know what Capistrano is?  I did a <a href="http://www.cosinewave.net/ruby/cap" title="Using Capistrano">presentation</a> on it in February, so I know a little about it.  At the time I was investigating it as a hopeful candidate that could assist with configuration management for general systems administration for an environment of about 150 Solaris systems.  I discovered that Capistrano is a fantastic program and a great tool for application deployment.  Honestly there is no reason you should ever put up with the act of moving an application to production being more than a few keystrokes, and using Capistrano makes that possible.  However, Capistrano was unable to help out such a large Unix environment.</p>
<p>Capistrano has no facility for continuing tasks upon failure.  In a large Unix environment, stuff needs to happen even if only 98% of the systems are up.  What about the 2% not available?  They can get the update later when they&#8217;re back.  We needed a tool that can just do the work and get it done on the 98% and report on who failed.  Later, when the failed systems are back online, the tool should automatically update them on the next run.  Then we can go about fixing the issues causing those 2% of systems to fail and rest assured that all our changes will be pushed soon.</p>
<p><span id="more-7"></span> I intend to fill this gap.  Jamis Buck, the maintainer of Capistrano, also wrote the Net::SSH module for Ruby.  It is a spectacular module.  With it, I plan to write an agentless tool that runs from a central server and uses SSH to log into each system for whatever task necessary.  Couple it with some tools to manage users, groups, system configurations, and software installations, and a new tool to conquer the world will be born.</p>
<p>If you want to conquer the world with me, let me know! <img src='http://cosine.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>I have written a similar tool before.  Back when I worked at Abbott I wrote a little tool we called confmgt.  I used Perl because when I started the project around 1999 or 2000 that was the best language I knew.  Additionally, Perl was installed on every Research and Development Unix system in the company, so I could count on it being present.  The original version ran on a central server and used rdist to push files to target hosts after performing some non-trivial logic on which files to include in and exclude from the transfer.</p>
<p>Eventually the tool grew and features were added, and by version 3.0 (the last major version when I left Abbott) the program used rsync by default and could be run either from central server or from the host being updated.  More complicated configurations required features to include more customization in how distribution areas were laid out.  Despite still being written in Perl, I was very proud of the 3.0 release of confmgt.  It was a masterpiece of Perl and of programming in general.  With this release other Unix administrators were no longer coming to me and asking for new features; instead they came, asked, and then left knowing how to do what they were requesting.  I have rarely felt greater pride in my work.</p>
<p>So now I am going to repeat myself, but this time in Ruby.  Instead of rsync I will use Net::SFTP.  The configuration file will likely be similar to Capistrano&#8217;s so that people familiar with one can use the other easily (as it should be!).  It is time to change the world.</p>
]]></content:encoded>
			<wfw:commentRss>http://cosine.org/2007/07/18/capistrano-administration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
