2019/03/26

Automating SSH tunnels

I need a persistent port forwarding configuration between two systems, where there may be more than one SSH jump between the two.  I want systemd to make sure it's running all the time.

A solution:
    # Systemd unit file for an SSH Tunnel service
    #
    [Service]
    Type=simple

    User=tunnel
    ExecStart=/usr/bin/ssh -F /home/tunnel/ssh-config-for-tunnel -vN tunnel.%i

    # On failure, wait 10 seconds to restart
    Restart=always
    RestartSec=10

    # 20 failures within a 10 minute window marks this service as failed.
    StartLimitInterval=600
    StartLimitBurst=20

    [Unit]
    Description="SSH Tunnel to %i"
    Requires=network-online.target

    [Install]
    WantedBy=multi-user.target
From here, I create a trusted keypair with
ssh-keygen -t ed25519
and configure the ssh-config-for-tunnel file:
# Configuration of the SSH tunnel from here to there
# Requirements:
#   This file in /home/tunnel/ssh-config-for-tunnel

#   Service /etc/systemd/system/ssh-tunnel@.service enabled and started
#
#   Additional tunnels can be enabled as ssh-tunnel@elsewhere.service

# Special defaults for tunnels
Host *
    ControlMaster no
    ExitOnForwardFailure yes
    IdentitiesOnly yes

#####################################################################
# Configure Tunnel:
#####################################################################
Host tunnel.myservice
    ### Connection:
    # Private IP of ultimate destination
    HostName 172.31.92.114
    # Identity on the CB master
    IdentityFile ~/.ssh/id_master
    # Public IP of Jump 1 bastion
    ProxyJump 192.168.100.142

    ### Tunnels:
    # Take near port :18443 and send it to master's listener
    LocalForward 8444 localhost:8443
    # Take far port :6100 and bring it back to local listener
    RemoteForward 6100 161.134.130.247:6100

# Jump configurations
Host 192.168.100.142
    # Configuration for the bastion system
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump 10.192.107.33

Host 10.192.107.33
    IdentityFile ~/.ssh/id_ed25519

This example connects from localhost to 10.192.107.33, then from there to 192.168.100.142, then from there to 172.31.92.114, the server that I need the tunnel to, and it sets up port forwarding from end to end, without trying to get the ports on the series of jump servers.

2019/01/11

Create a python virtualenvironment and matching Jupyter kernel

I often work in Jupyter notebook for python scriptlets, and if there's a special package I need, I'd rather not pollute my global python environment. The answer, of course, is virtualenv and a jupyter kernel that references that venv, which I have to look up the command for every time.

 Automation to the rescue-- here's newkernel.cmd:

@echo off
REM newkernel.bat - create a python virtualenv and register it as a
REM Jupyter kernel
REM

SET /P _envname="Name of environment:"
if "%_envname%x" NEQ "x" goto :got_name
@REM else
     set _envname=py-%USERNAME%-%RANDOM%
@REM fi
:got_name

C:\tools\Anaconda3\python.exe -m venv %_envname%.venv

set /P _envkern="Kernel name:"
if "%_envkern%x" NEQ "x" goto :got_kern
@REM else
     set _envkern=py-%_envname%
@REM fi
:got_kern

set /P _envdesc="Kernel Description:"
if "%_envdesc%x" NEQ "x" goto :got_desc
@REM else
     set _envdesc="Python (%_envname%)"
@REM fi
:got_desc

%_envname%.venv\scripts\pip install ipykernel
%_envname%.venv\scripts\python -m ipykernel install --name %_envkern% --display-name "%_envdesc%"

2018/03/06

Automatically renew internal SSL certificates (DRAC and Windows)

A bunch of our DRACs have certificates that are about to expire.  I know I could go in and generate a new CSR in each web interface, copy them into the AD Certificate Services, and upload the results (that's how the previous admin did it) but.... I'm lazy.

Plus, new certificates generated that way still give a big warning since Chrome 58-- they don't have the X509v3 SAN extension which is now mandatory apparently.


C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcsrgen -g -f dracname.dom.ain.csr
Security Alert: Certificate is invalid - Name on Certificate is invalid or does not match site name
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors.
CSR generated and downloaded from RAC successfully

C:\> certreq -submit -attrib "san:dns=dracname.dom.ain\nCertificateTemplate: WebServer" dracname.dom.ain.csr dracname.dom.ain.crt
Active Directory Enrollment Policy
  {BFF41397-4CCE-41B5-AD8E-A029B2C2353B}
  ldap:
RequestId: 104238
RequestId: "104238"
Certificate retrieved(Issued) Issued  The certificate validity period will be shorter than the WebServer Certificate Tem
plate specifies, because the template validity period is longer than the maximum certificate validity period allowed by 
the CA.  Consider renewing the CA certificate, reducing the template validity period, or increasing the registry validit
y period.

C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcertupload -t 1 -f dracname.dom.ain.crt
Security Alert: Certificate is invalid - Name on Certificate is invalid or does not match site name
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors.
Certificate successfully uploaded to the RAC. The RAC will now
reset to enable the new certificate and may be offline temporarily.

C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcertview -t 1
Serial Number            : redacted

Subject Information:
Country Code (CC)        : AU
State (S)                : Some-State
Locality (L)             : MyTown
Organization (O)         : Internet Widgits Pty Ltd
Organizational Unit (OU) : World Wide Web Pty Ltd
Common Name (CN)         : *.dom.ain

Issuer Information:
Common Name (CN)         : AD DOM.AIN Root Trust CA

Valid From               : Mar  6 16:01:02 2018 GMT
Valid To                 : Nov  6 15:13:19 2019 GMT

And the warning goes away for another year. And it took me less time to figure out how to automate it (throw the above commands into a .bat) than it would have to loop through all of them with a browser!

--Joe

2017/06/18

iPhone backup that wasn't

Spent a bit of time this weekend trying to help my cousin copy everything off of her iPhone 6, so that it can be wiped and transferred to another person.  But since I'm stubborn and contrary, I didn't want to do it in iTunes (plus I didn't have her password)...

Enter libimobiledevice, and idevicebackup, referenced by a nice post from Santoku Linux https://santoku-linux.com/howto/mobile-forensics/howto-create-a-logical-backup-of-an-ios-device-using-libimobiledevice-on-santoku-linux/ .  But since I'm stubborn and contrary, the CD image wouldn't install in VirtualBox on my laptop.  Sigh.  Ok, build from source.  Vagrant ubuntu, then clone libimobiledevice and just about all the other pieces of their github, run idevicebackup and... well, this iPhone is too new, try using idevicebackup2.  Cool, backing up, ##### marks dancing across the screen in little boxes, stuff being written unencrypted to disk, excellent.

Verify that the backup is readable and not encrypted, sweeet.  Now what did I get in my 2.5GB of disk space?  I still have no idea.

idevicebackup has an "unback" command that should convert the plist and SQLite files into a meaningful folder structure, which is said to work on version of IOS > 6.  Unfortunately, the feature on the phone (which needs to be plugged in) that they were using to read and translate the backup was broken between IOS 10.3.0 and 10.3.1 (this fact was, and still is undocumented in the toolset, except for the closed github issue).  So unback is not available.

End state: 2.5GB of possibly-useful-in-the-future data, and a wiped iPhone.   Oh well, that's life on the bleeding edge of tech.

2017/04/26

What I've learned today

A couple of useful Java tricks that I can't find consolidated elsewhere on the web:

Locking down Java: 

I have a Java instance that runs just my one application. (for example, /opt/foo/jre/bin/java) This application talks across systems, and can be set to use SSL. I don't want to pay for a "real" certificate-- I'll use our internal CA, besides, I don't really want to trust Verisign or any of the other 300+ CAs that Oracle/IBM have decided they like. (No offense intended, just paranoia about MITM attacks within my LAN)

Let's assume that I have this part working, and that SSL is being served happily on the first server.
I'll start by extracting the certificate chain from that first server:
:| openssl s_client -host firstinstance -port 8443 -prexit \
           -showcerts >firstinstance.crt
(No, that's not an emotionless command emoticon, it's a pipe)

From there, I can manipulate the Java keystore to trust (or not trust) my targets.
keytool -import -alias firstinstance -file firstinstance.crt \
  -keystore paranoid.jks -storepass changeme -noprompt \
  && cp paranoid.jks /opt/foo/jre/lib/security/cacerts

Did it work?:

Well, let's check.  Using the same Java environment as our app:
$ JRE_HOME=/opt/foo/jre
$ JAVA_HOME=/opt/foo/jre
$ /opt/foo/jre/bin/java -cp . SSLPoke firstinstance 8443
Successfully connected
In theory, a restart of the app should have it pick up the new (single-entry) list of trusted certificates. In practice...

WTF file is it loading from?

Hidden somewhere in the depths of the startup script for the app, something gets redefined so that instead of looking in $JAVA_HOME/lib/security/cacerts (which has been nicely cleaned up), it used /opt/foo/lib/security/cacerts. (But of course, I didn't know that until.. Hammer)
# apt-get install -y sysdig
# sysdig proc.name=java and evt.type=open | grep cacerts & systemctl restart foo
#7554308 14:25:48.107476643 3 java (6613) < open fd=22(/opt/foo/lib/security/cacerts) name=/opt/foo/lib/security/cacerts flags=1(O_RDONLY) mode=0 
Ah, there's the file I need to mangle for my application.

You may have noticed I slipped in the SSLPoke command above. That's a fetch of https://confluence.atlassian.com/download/attachments/117455/SSLPoke.java -- Thanks, #Atlassian!