Saturday, February 18, 2017

Adding a JST serial connector to the PogoPlug Mobile

Embedded ARM is a very popular platform for building appliances these days, everything from NAS, Wi-Fi access points, and media players, to tablets, smartphones, and smartmeters.

Not all ideas are as successful as others, which means that once in a while you can get yourself an ARM board for pennies on the dollar. One such case is the PogoPlug. Originally sold for $50 and up as a cloud-connected storage appliance, they can now be acquired for as little as $7.50.

Of course, to make any use of these devices you'll need to access and replace the operating system. And the cheapest version of the device has no serial connector, no external shell access, and is not supported by the company that manufactured it.

The older versions of the PogoPlug have a nice JST header that offers serial access to the bootloader and Linux shell. Those can be found for as little as $10. But why spend $2.50 more when you can just attach your own JST connector to the cheaper model? I know, I know, it will cost much more in supplies and tools to do that...but it's also a little more fun.

First, here are a few before pictures of my PogoPlug Mobile. As you can see, this is the version that offers SD, SATA, and USB connection options. Network connectivity is Ethernet, no Wi-Fi.




My goal is to show an option for adding a serial console with a JST connector. That way you can use an audio cable and a USB-to-TTL adapter to connect it to your computer. This board makes this a little tricky, hence the post.

I aim to make this so clear that even a software engineer (like myself) with a soldering iron can do it successfully.

First, the tools you'll need (I'll provide links for these at the end of the post):
  • Solder paste
  • Wire cutters
  • Flux
  • Solder wick
  • Solder
  • Soldering iron
  • Screwdriver
  • Scraper
  • Soldering iron tip cleaner
  • JST female connectors
  • Audio cable with JST male connector and H4PL connector
  • USB-to-TTL adapter



So, go buy all this stuff so that you can save $2.50. Got it? Good.

Now we disassemble the PogoPlug. Flip it over and remove the two bottom rubber feet, exposing two screws. Remove the screws and work the scraper tool into the slot between the top and bottom covers. As you move the tool toward the front of the PogoPlug, push inward to separate the tabs that hold the top and bottom together. There is a tab on each side and two more on the front. If you snap one or two tabs, don't sweat it -- the screws will hold it together when you're finished.





Remove the four small screws that hold the board to the bottom plate and you'll have a bare board, ready for modification.

On the bottom right side of the board, just below the SD card socket there are four pads in a straight vertical line with a white box drawn around them. This is where our JST connector will be soldered in place. From the top to the bottom, they are ground, transmit, and receive. We won't use the bottom one, it supplies voltage that isn't needed for serial console.

Here's a picture of the bottom of the board. The four pads are on the bottom left.



Here we can see a little problem. The pad for ground (farthest right) looks different from the others, like there's a ball of solder sitting on the board. As far as I can tell, that's exactly what it is. What appears to be a hole on the top of the board is not a hole at all.



So, how do we attach a JST connector with four pins to a board with three holes?

Let's not get too far ahead of ourselves here. First, we should clean up the other three pads, which actually are holes through the board. Using the solder wick, flux, the soldering iron, we can remove all the solder from those holes pretty easily.

If you are already experienced using a soldering iron, perhaps an electrical engineer, please:
  1. Don't laugh at the next part.
  2. Feel free to skip this next bit.
  3. Realize that this is a remedial soldering lesson for the hardware-impaired.
  4. Leave constructive feedback in the comments section.
My solder wick was much more effective when I added some flux to it. The wick was supposed to already have flux in it, but it didn't soak up any solder for me until I added a healthy amount of flux to it.



Get your iron hot, clean the tip, and add a bit of solder to the tip (this is called "tinning"). Dab the tip to the pad to add some solder to it. This might seem counter-intuitive, since we're trying to remove the solder. However, a little more solder helps to transfer the heat to the solder inside the hole, melt it, and remove it.

Put the solder wick on top of the pad and press the soldering iron tip on the wick directly above the pad. The solder on the tip should be absorbed into the top side of the wick, and the solder on the pad should absorb the heat, melt, and be absorbed into the bottom side of the wick.

This might not work 100% the first, second, or even the third time you try. You might have to do it on the top and the bottom of the board. When you do it right, the holes will be clean and pretty. Note that I didn't clean up the ground pad much -- I did remove what I could with minimal effort, but nothing more.


So, back to the question -- how do we attach a JST connector with four pins to a board with three holes?

I let the smoke out of one board trying to figure that out, but I eventually found a way that worked for me.

The pad looks like a surface mount, so I clipped the pin on the JST and used solder paste to connect it to the surface of the pad. Solder paste melts at a lower temperature, so it's easier to use it than it would be to use regular solder.


You have to leave enough pin to be able to make the connection, but remove enough to let the connector sit close to the board. Here's how mine ended up.


This is also a good time to make sure you got enough solder removed from the other three holes. Put the connector in the board, making sure the pins go through easily and that it sits close to the board.




Now we add a little ball of solder paste to the pin and ground pad. Not too much -- you want the paste to stay only on the ground pad without leaking somewhere else when it melts. Apply heat on the bottom of the pad and the top of the pin with the soldering iron.






I don't recommend moving or pulling on the connector at this point. All you need is a decent electrical connection, not a solid mechanical one. The other three will hold it in place.

Put a litte flux on the other three pads and solder the remaining three pins from the bottom side. Here's how it looked when the soldering was done. Not terribly pretty, but functional (and prettier than some of the others I've seen).





The hard part is done! Now all we have to do is modify the cable to put ground, transmit, and receive on the right wires.

Use a push pin, thumb tack, or the scraper to lift the covers that secure the wires to the H4PL connector and pull the wires out one-by-one.


Since I wanted a permanent serial console available without disassembling the PogoPlug, I melted a hole in the cover and inserted the audio cable through it.



Then I connected the pins to the H4PL connector again, this time in the order that works with the USB-to-TTL adapter I bought. Pretty simple: ground-to-ground, transmit-to-receive, receive-to-transmit.

Before:

After:





Plug in both sides of the audio (now serial) cable, plug it into USB on your computer, and fire up your favorite serial communication program. I prefer minicom.





U-boot, shell, woot!








At this point you'll want to enable remote shell and disable the PogoPlug software. To do that, remount the root filesystem read-write:

mount -oremount,rw /

Then edit /etc/init.d/rcS, commented the last line, and added two lines to allow remote shell access. The last line used to look like this:

/etc/init.d/hbmgr.sh start

Now it looks like this:


#/etc/init.d/hbmgr.sh start
telnetd
/usr/sbin/dropbear

Execute "poweroff" and unplug the unit. Now button it all back up and start hacking away. Sites that provide guidance for replacing u-boot and running your own customized Linux can be found in the section at the end.

Here's my final product. Again, not the prettiest, but very functional.



Credits:
Moustafa Hassan
Qui's techNOLOGY Blog
Discovering solder paste
Jeff Doozan Linux Device Hacking Forum


Links to supplies and tools (all sellers based in USA, because I'm impatient):
PogoPlug on the cheap:

Friday, January 15, 2016

Generating certificates with Subject Alternative Name (SAN) using OpenSSL

SSL's Subject Alternative Name (SAN) allows you to specify multiple names on a single certificate.  In my case, this allows me to validate a certificate whether I'm communicating with the service by name or IP address.

I'm guessing most people would just tell their certificate broker they want a SAN and what the SAN should contain.  I'm running my own CA, so the nuts and bolts of doing this became more important.  Like most things, the "doing" is easy....it's the "knowing what to do" that was a little painful.

For my purposes, I need to be generate certificates via a script with no human interaction.  Since I need to know my host's name and IP address, I grab them from the OS:

my_hn=$(hostname)
my_ip=$(ip a show dev eth0 | awk '/inet / { split($2, a, /\//); print a[1]; }' | head -n1)


OpenSSL config files allow me to read these environment variables, which makes automation much simpler, as you'll see below.
First, I'll assume you already have a certificate authority with the requisite keys.  First, generate a key named "my.key":

openssl genrsa -rand /dev/urand -out my.key 2048

We need to create a config file for the next two commands.  You can specify these things on the command line, but it was easier for me to put them in a file.  My config, which I named "my.cnf", looks something like this:

[ req ]
prompt             = no
req_extensions     = v3_req
default_bits       = 2048
distinguished_name = req_distinguished_name
string_mask        = utf8only

[ req_distinguished_name ]
countryName            = US
stateOrProvinceName    = Colorado
localityName           = Rocky Mountains
organizationName       = Snow
organizationalUnitName = Adventure
emailAddress           = rmsa@example.com
commonName             = $ENV::MY_HN

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage         = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName   = @alt_names


[ alt_names ]
IP0  = $ENV::MY_IP
DNS0 = $ENG::MY_HN

Note that you can specify multiple IP addresses and DNS names in the SAN, assuming you calter the file and the commands below accordingly.

Now, the first part of the magic.  Generate a certificate signing request named "my.csr" (note that we pass in the env variables the config file is expecting to read):

MY_HN="$my_hn" MY_IP="$my_ip" openssl req -new -key my.key -out my.csr -config my.cnf

What I've written so far is pretty well documented on several blogs like mine.  This next part isn't. When you sign the CSR, you must specify the same extensions with the "-extension" and "-extfile" options.  We can use the same config file, as long as we pass in the variables like we did when generating the CSR.

The command below will generate "my.pem".  Note that we pass in the same variables, use the same config, and use my certificate authority's public key (myca.pem) and private key (myca.key):
MY_HN="$my_hn" MY_IP="$my_ip" openssl x509 -req -in my.csr -CA myca.pem -CAkey myca.key -CAcreateserial -extensions v3_req -extfile my.cnf -out my.pem -days 365

To test it, import "myca.pem" into your browser's trusted CA list.  When you install this certificate (my.pem) on a web server,  you'll be able to browse to that site via name or IP address without complaints or warning.  Inspect the certificate and you'll see something like this:
 

If you see the Subject Alternative Name in the Subject field, you didn't add the extensions when you signed the certificate.  That's what I was struggling with initially.  Here's what it looks like when it's wrong:

Thursday, June 25, 2015

Ubuntu Upstart unkown job

First, let me express my affection for startup scripts.  The ability to run a shell script directly, modify its contents freely, use familiar tools and tactics for debugging -- it's the epitome of beauty in simplicity.  SysV Init is elegant, effective, and easy to use.

Obviously, Ubuntu just couldn't live with that, so they replaced it with the ever-complicated and uppity Upstart.  Yes, it can start my laptop up in 10 seconds instead of 15.  Yes, it's event-driven.  Yes, it uses fancy private sockets and DBUS infrastructure and uber secure architecture.  Yes, the syntax is mysterious and unfamiliar.  Yes, it's a royal pain in the butt.

An issue that has plagued me for many moons is this:

asmith@asmith-hp:~$ sudo restart ssh
restart: Unknown job: ssh
asmith@asmith-hp:~$ sudo restart vsftpd
restart: Unknown job: vsftpd
asmith@asmith-hp:~$ sudo restart tftpd-hpa
restart: Unknown job: tftpd-hpa


Why can't I, the lowly, unprivileged user, manage ANY of my services?  Rather than find the service you're trying to control, initctl simply tells you your job doesn't exist.  After a bit of searching, I was gifted this answer.

asmith@asmith-hp:~$ man initctl
...

       --system
              Communication  with the init(8) daemon is normally performed over a private socket connection.  This has the advantage of speed and robustness, when issuing commands to start or stop services or even reboot the system you do not want to be affected by changes to the D-Bus system bus daemon.

              The disadvantage to using the private socket however is security, init(8) only permits the root user to communicate over this socket which means that read-only  commands such as status and list cannot be made by other users.

              The --system option instructs initctl to communicate via the D-Bus system bus rather than over the private socket.

              This  is  only  possible  if  the  system  bus  daemon is running and if init(8) is connected to it.  The advantage is that the default security configuration allows non-root users to use read-only commands.

...

In short, Upstart also manages services for the user session, which is kept separate from system service management.  When you run upstart management commands as a non-root user, it manages your user session services rather than the system services.  To manage those important system services, you must add "--system" to the command like so:

asmith@asmith-hp:~$ sudo restart --system ssh
ssh start/running, process 19645
asmith@asmith-hp:~$ sudo restart --system vsftpd
vsftpd start/running, process 19651
asmith@asmith-hp:~$ sudo restart --system tftpd-hpa
tftpd-hpa start/running


A note to Upstart developers: I'm a software engineer, too.  I'm probably about as lazy as you, and at times as unconcerned about the user experience as you are.  It's very easy to make things very difficult for the user.  If you train the user to do something a certain way, then change the way it's done, you MUST BE LOUD about it!  Switching from simple SysV scripts to Upstart was mean, but then changing the way Upstart works without helpful hints to the user was simply sadistic.

Do you think you could have at least searched for the requested service name over DBUS?  Heck, maybe only do that when the user is running the command via sudo, or some other way with root permissions.  Then, maybe you could emit a helpful message like this:

"warning: future versions will require you to use the '--system' argument to manage system-level services.  For example: restart --system ssh"

Other programs, like SSH, work like this.  I love SSH.  Even when SSH changes (like how the known keys are stored and managed), they will always look out for the little guy by giving hints and example commands that can simply be copied and pasted at the command line.

Upstart, may you turn from your secretive, pedantic, obscure ways and become one with those you serve.

Tuesday, February 05, 2013

Moving Linux to a new hard drive

Move your files

This assumes that you've already partitioned and formatted all partitions on the new drive. Remember to mark the boot partition as bootable.

Mount the new hard drive and sync all files:

sudo -s
mkdir -p /mnt/newdrive
mount /dev/sdb1 /mnt/newdrive
rsync -avx / /mnt/newdrive/
# repeat for other mountpoints as appropriate

Change the UUID

Now you'll need to edit all config files that use the hard drive's UUID (like /mnt/newdrive/etc/fstab) and change all UUID entries to match the new drive.  In vim, this handy command will give you a headstart:

:r !ls -l /dev/disk/by-uuid

Install bootloader

For the next step I like to physically install the drive and boot up from a live Linux CD.  Once you're in, run:

sudo -s
mkdir -p /mnt/newdrive
mount /dev/sdb1 /mnt/newdrive
chroot /mnt/newdrive /bin/bash
grub-mkdevicemap
grub-install /dev/sda
update-grub2
update-initramfs -c -k all
exit

Wrap it up, stick a bow on it

Cross your fingers and reboot!  If it doesn't come up, check your partitions, making sure the correct one is marked bootable, and verify that your fstab entries are all correct.  Remember that Ubuntu-based systems might hang for over 2 minutes on boot if networking isn't available, so be patient.

Friday, February 01, 2013

Linux SSD setup and tuning

Just a few notes as I move to a new SSD.  Setting it up correctly from the beginning should help drive performance and longevity.

In /etc/rc.local, add
hdparm -W1a0A0 /dev/sda


From http://apcmag.com/how-to-maximise-ssd-performance-with-linux.htm

Partition alignment

This can only be done with a clean system before you install either Linux or Windows. Partition alignment is critical for SSDs as, being memory-based devices, data is written and read in blocks known as pages. When partitions aren't aligned, the block size of filesystem writes isn't aligned to the block size of the SSD, causing extra overhead as data crosses page boundaries.

Aligning partitions is simply a matter of ensuring the first partition starts on a clean 1MB boundary from the start of the disk, ensuring whatever block size the filesystem uses will align with the block size of the SSD (which can also vary). If you create partitions using Windows 7 on an empty drive, it will start partitions at the 1MB boundary automatically.

In Linux, simply run 'fdisk -cu (device)' on the drive you want to partition, press 'n' for new partition, 'p' for primary and enter a start sector of at least 2,048. The general rule is that the starting sector must be divisible by 512, but to cater for all variations of SSD page size and filesystem block size, 2,048 is a good idea (and equates to 1MB).

*Note -- if you use LVM on a bootable partition, grub2 needs to put more code at the beginning of the drive, so you might want to leave even more headroom before the first partition.

Scheduler

For Ubuntu and other distributions using GRUB2, edit the /etc/default/grub file and add 'deadline' to the GRUB_CMDLINE_LINUX_DEFAULT line like so:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash elevator=deadline"

Then run 'sudo update-grub2'.

Applications

Any applications that write excessively to a hard drive are also candidates for moving data. Browsers are a fine example of this -- the browser cache is nice, but it'd work just as well from a spinning platter drive and save your SSD from thousands of writes a day that don't make a huge difference to you.

To move the cache in Firefox, in the browser type 'about:config', right-click anywhere and select New --> String, and add 'browser.cache.disk.parent_directory'. Edit the variable and point it to a directory on a non-SSD drive or, if you don't mind losing the cache between boots and you're using the tweaks above, point it to /tmp for a super-fast memory cache.

Moving the cache in Chrome is a little harder. The directory is hardcoded, but you can use symbolic links to point it to a directory on another drive or to /tmp. You'll find the cache under ~/.cache/chromium. You could also redirect the entire .cache direct
Applications
ory, as many programs use this for caching data.


From http://wiki.freeswitch.org/wiki/SSD_Tuning_for_Linux

Using tmpfs to reduce drive usage

 tmpfs                /ramdisk             tmpfs nodev,nosuid,noatime,mode=1777,size=100M 0 0 
 tmpfs                /tmp                 tmpfs defaults,noatime,mode=1777   0  0 
 #tmpfs               /var/spool           tmpfs defaults,noatime,mode=1777   0  0 
 tmpfs                /var/tmp             tmpfs defaults,noatime,mode=1777   0  0
 #  .thumbnails files are never deleted and can grow quite large over time.
 tmpfs                /root/.thumbnails    tmpfs defaults,noatime,mode=1777   0  0
 tmpfs                /home/mario/.thumbnails    tmpfs defaults,noatime,mode=1777   0  0

*Note -- I removed the /var/spool mount point because it messes up user cron jobs and mail server services.

Swappiness

This only applies if the swap file is moved to the SSD. The swappiness value affects the activity of the swap file. If you placed the swap file on the SSD you should reduce the swappiness of Linux. There are many good explanations but simply put: Linux tries to anticipate when something might need to be swapped and does it anyway. By reducing swappiness Linux is less likely to do this so swap writes are reduced. Swappiness is a value from 0 to 100, the higher the more swappiness. You can check your current value using:
   cat /proc/sys/vm/swappiness
There are a couple of different ways to change swappiness permanently. I changed this system from it's default of 60 to 1 by adding the following to /etc/sysctl.conf:
   vm.swappiness=1
   vm.vfs_cache_pressure=50



Thursday, August 16, 2012

IPv6 Madness

I've been doing some playing with IPv6 lately, since the world is out of IPv4 addresses (wait, didn't that happen a long time ago???  Whatever...).  It's been really interesting to learn about the actual protocol and how it works compared to IPv4.  I've got a fully routed /64 IPv6 network at home, but just a couple systems at home using auto-configured IPv6 address.  I've thoroughly enjoyed it, especially because I've been putting off learning about it for so long (truth be told, I was a bit intimidated by it -- didn't need to be).

If you want to play with IPv6 and your ISP doesn't yet support native IPv6, you can easily set up a tunnel through http://www.tunnelbroker.net/ (provided by Hurricane Electric Internet Services) for free.  They also have free DNS hosting (with full support for AAAA and reverse IPv6 records, of course) and they offer a free, online IPv6 certification (I got to the "Sage" level last week).

IPv6 Certification Badge for soccergeek

I found IPv6 Essentials from O'Reilly to be very helpful in understanding how it all comes together.  You can get it in a DRM-free ebook format from O'Reilly's site, which is pretty awesome.