Technical

Last modified by Mitchell on 2022/01/22 09:19

35 posts

Feb 22 2020

More building blocks

As I'd mentioned before, one thing I've been picked up over the past few years is Kubernetes. By default, it's designed for large-scale deployments with a declarative approach toward configuration. There are a number of attractive features that it offers, even for small installations, however, such as:

  • Easier upgrading
    • Delete a pod and it'll redeploy itself with whatever the newest Docker container is - with the caveat that you're using upstream Docker containers, though.
  • Better separation of configuration and data versus executables
    • A single YAML file can contain the entire service configuration, and directories can be mapped in for persistent data.
  • Better scalability
    • Virtual machines inherently use more resources than containers due to needing to emulate more of the stack.

There is, admittedly, more complexity involved in maintaining such a system, but it's still manageable, and I feel that in this case the benefits outweigh the costs. So, what's involved? (Note: I'm not going to be spending much time explaining how Kubernetes works here, since that would end up taking entirely too much time. There are quite a few tutorials out there if you're interested in learning.)

Having looked around at a couple of alternatives, I've found that I'm fairly happy with k3s, which is an abbreviated Kubernetes (also known as k8s) (and, yes, that's a rather awful joke). For now, I've been using a single-node deployment, although it's pretty easy to scale it out as well. The recommend way of installing it using curl, largely for safety reasons:

$ curl -sfL https://get.k3s.io | sh -

If you're feeling brave and/or trust Rancher (the company behind k3s) enough and/or don't feel like installing curl, you can use wget instead:

$ wget -qO - https://get.k3s.io | sh -

The installation should be painless. After installation has completed, you should be able to do a check that Kubernetes is running:

$ kubectl get -n kube-system pods
NAME                                      READY   STATUS              RESTARTS   AGE
metrics-server-6d684c7b5-jl842            0/1     ContainerCreating   0          11s
coredns-d798c9dd-k9rrc                    0/1     ContainerCreating   0          11s
local-path-provisioner-58fb86bdfd-2xvbp   0/1     ContainerCreating   0          11s
helm-install-traefik-2x8c7                0/1     ContainerCreating   0          11s

At this point, we can use a modified simple YAML file from Docker introducing Kubernetes support within Docker (the changes are to migrate deployments from apps/v1beta to app/v1 and to use an Ingress instead of a NodePort):

docker-demo.yaml
apiVersion: v1
kind: Service
metadata:
 name: db
 labels:
   app: words-db
spec:
 ports:
    - port: 5432
     targetPort: 5432
     name: db
 selector:
   app: words-db
 clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: db
 labels:
   app: words-db
spec:
 selector:
   matchLabels:
     app: words-db
 template:
   metadata:
     labels:
       app: words-db
   spec:
     containers:
      - name: db
       image: dockersamples/k8s-wordsmith-db
       ports:
        - containerPort: 5432
         name: db
---
apiVersion: v1
kind: Service
metadata:
 name: words
 labels:
   app: words-api
spec:
 ports:
    - port: 8080
     targetPort: 8080
     name: api
 selector:
   app: words-api
 clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: words
 labels:
   app: words-api
spec:
 replicas: 5
 selector:
   matchLabels:
     app: words-api
 template:
   metadata:
     labels:
       app: words-api
   spec:
     containers:
      - name: words
       image: dockersamples/k8s-wordsmith-api
       ports:
        - containerPort: 8080
         name: api
---
apiVersion: v1
kind: Service
metadata:
 name: web
 labels:
   app: words-web
spec:
 ports:
    - port: 8081
     targetPort: 80
     name: web
 selector:
   app: words-web
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: web
 labels:
   app: words-web
spec:
 selector:
   matchLabels:
     app: words-web
 template:
   metadata:
     labels:
       app: words-web
   spec:
     containers:
      - name: web
       image: dockersamples/k8s-wordsmith-web
       ports:
        - containerPort: 80
         name: words-web
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: ingress
spec:
 rules:
  - host: <hostname>
   http:
     paths:
      - path: /
       backend:
         serviceName: web
         servicePort: 8081

I'm also rather fond of the k3s demo put together by a Rancher support engineer, but it doesn't work correctly on newer versions of k3s due to Traefik now setting /ping as a keepalive port (which collides with this app's querying of that URL). It's not too hard to fix it, but it requires either building yet another Docker container (minor changes needed to both main.go and templates/index.html.tmpl) or disabling Traefik's use of /ping, and I don't quite care enough to jump through those hoops. 😛

k3s-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: rancher-demo
 labels:
   app: rancher-demo
spec:
 replicas: 1
 selector:
   matchLabels:
     app: rancher-demo
 template:
   metadata:
     labels:
       app: rancher-demo
   spec:
     containers:
      - name: rancher-demo
       image: superseb/rancher-demo
       ports:
        - containerPort: 8080
---
kind: Service
apiVersion: v1
metadata:
 name: rancher-demo-service
spec:
 selector:
   app: rancher-demo
 ports:
  - protocol: TCP
   port: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: rancher-demo-ingress
spec:
 rules:
  - host: <hostname>
   http:
     paths:
      - path: /
       backend:
         serviceName: rancher-demo-service
         servicePort: 8080

The <hostname> in the Ingress specified at the end should be updated with your test domain name. Write it to disk, then load it up into Kubernetes. We can see the components loading up shortly afterward:

$ kubectl apply -f kube-deployment.yml
service/db created
deployment.apps/db created
service/words created
deployment.apps/words created
service/web created
deployment.apps/web created
ingress.extensions/ingress created
$ kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
db-77f4c964c-9xsq6      1/1     Running   0          4s
web-7fdc45cb65-m744g    1/1     Running   0          4s
words-8b7cc4ff8-j2m2l   1/1     Running   0          4s
words-8b7cc4ff8-2v7xf   1/1     Running   0          4s
words-8b7cc4ff8-fjcgw   1/1     Running   0          4s
words-8b7cc4ff8-x5gtb   1/1     Running   0          4s
words-8b7cc4ff8-cfqdt   1/1     Running   0          4s

At that point, you can go to your domain and verify that it works. The different pods are used as a pool to query nouns/verbs/adjectives, with the IP of the serving pod listed at the bottom of each block. Each reload should show a different set of words/IPs. Congratulations! Although, you probably do want to secure your system, but that's an exercise left up to the reader.

Feb 17 2020

Press OK for certificate

When setting up internal services (using Alpine Linux, there's generally a need for certificates for securing internal communication. I brushed over it previously, but a few additional comments about that:

  • Encrypting internal communication is a good idea as there are multiple possibilities for eavesdroppers for internal traffic:
    • If you have any servers that allow multiple users (particularly with interactive shells), those users could be sniff network traffic.
    • Treat systems (whether servers or containers) as though when they'll be compromised, not if. There's ultimately no such thing as a piece of software that has no vulnerabilities, so your infrastructure should have layered defenses.
  • I ultimately don't like wildcard certificates across multiple systems, as if one of those systems is compromised, you've given up a large chunk of that asymmetric encryption. Naturally, if you have multiple services on a single system, then sharing a certificate across those services (with, say, a multi-domain certificate) isn't as much of an issue.

From a brief look at various PKI implementations, I settled on OpenXPKI as something that would be fairly easy to use and maintain for the size of what I'm maintaining. EJBCA is, of course, a much more widely-used CA implementation, but it's also more heavyweight than what I'm looking for. As a bonus, OpenXPKI is the primary target for CertNanny, which allows for automated certificate renewal via SCEP. Taking a look at the other open source software that implements a SCEP client, most of it hasn't been updated for considerably longer than CertNanny, other than jSCEP. And, well, I'm trying to avoid running Java where I can, due to how much Java loves chewing through resources (also applies to EJBCA). 😕

I won't be going into installing and setting up OpenXPKI here, although I will mention that needing to install Debian to install the official packages is annoying. I've been reluctant to use a container (due to wanting to treat my CA as core infrastructure), but I may switch over to that at some point in the future.... Just remember to also install openca-tools as well, which isn't listed in the Quickstart documentation, but is needed for SCEP to function.

A few changes/bugfixes are necessary to OpenXPKI so that it works correctly with SCEP:

  • If your realm has a profile/I18N_OPENXPKI_PROFILE_TLS_SERVER.yaml (if your OpenXPKI is old enough), update your 05_advanced_style section to add this section beneath subject (this brings it up to the current definition, which allows for specifying SANs on advanced requests, which we need):
I18N_OPENXPKI_PROFILE_TLS_SERVER.yaml
.
.
.
            san:
                - san_ipv4
                - san_dns
.
.
.
  • Edit your realm's profile/template/san_dns.yaml, and change the top line, as OpenSSL doesn't like SANs being specified with dns, only DNS:
san_dns.yaml
id: DNS
.
.
.
  • After these changes, restart the OpenXPKI daemon so that it reloads the templates.

The service for this example will be PostgreSQL. After starting with the usual Alpine Linux installation and configuration steps is adding PostgreSQL itself:

$ apk add postgresql

As per the PostgreSQL documentation, enable SSL in postgresql.conf. Now comes the interesting part: auto-generating server certificates. First off is installing sscep and CertNanny. If your CertNanny installation did not install a JDK, make sure you do so.

sscep and CertNanny aren't available on Alpine Linux by default. You can either build it yourself (fairly straightforward) or wait for me to provide packages.

A fix is needed for the code here as well:

  • Edit your CertNanny's lib/perl/CertNanny/Config.pm and lib/perl/CertNanny/Util.pm so that the openssl calls now use -sha1 instead of -sha:
Config.pm
    my @cmd = (qq("$openssl"), 'dgst', '-sha1', qq("$file"));
Util.pm
      my @cmd = (qq("$openssl"), 'dgst', '-sha1', qq("$tmpfile"));

Then, the CertNanny configuration files need to be set up. The simplest way is to copy the template files and modify them. Key sections to modify include:

Keystore-DEFAULT.cfg
  • keystore.DEFAULT.enroll.sscep.URL: set to your OpenXPKI SCEP URL (by default, http://<server>/scep/). sscep enforces using a non-SSL connection, as the connection is (in theory) already encrypted.
Keystore-OpenSSL.cfg

This is the default file we'll be using, since OpenSSL PEM is the de-facto standard on Linux. For PostgreSQL, we're not even concerned about the default entries, since we know where to put the file and that we don't want the server key encrypted. We also want the PostgreSQL server restarted whenever a new key is installed:

Keystore-OpenSSL.cfg
keystore.openssl.type                               = OpenSSL
keystore.openssl.location                           = /var/lib/postgresql/12/data/server.crt
keystore.openssl.format                             = PEM
keystore.openssl.key.file                           = /var/lib/postgresql/12/data/server.key
keystore.openssl.key.type                           = OpenSSL
keystore.openssl.key.format                         = PEM

keystore.openssl.hook.renewal.install.post          = /sbin/rc-service postgresql restart
certnanny.cfg
  • cmd.sscep: set to the path of your sscep binary.
  • Uncomment the include Keystore-OpenSSL.cfg line.

Then, some directory setup:

$ mkdir -p /var/CertNanny/state
$ mkdir -p /var/CertNanny/tmp
$ mkdir -p /var/CertNanny/AuthoritativeRootcerts

Put a copy of your root certificate into /var/CertNanny/AuthoritativeRootcerts so that sscep can validate your certificates.

Finally, we can set up automated certificate renewals. For the initial enrollment, use OpenXPKI to create an initial certificate (it uses these as a basis for certificate settings). However, the certificate will need to go through the Extended naming style to perform the following modifications:

  • The CN will need to have a suffix of :pkiclient (i.e. CN=<server>:pkiclient), which is the OpenXPKI default for auto-renewing certificates.
  • The SAN entries should be all FQDNs the server will listen on, including the hostname used to generate the CN.

The generated certificate and key should then be placed in the locations specified previously in Keystore-OpenSSL.cfg. At this point, you should be clear to enroll the certificate:

$ certnanny --cfg <prefix>/etc/certnanny.cfg enroll

You may need to accept the enrollment within OpenXPKI. And then, if you would like to verify, force a renew.

$ certnanny --cfg <prefix>/etc/certnanny.cfg renew --force

Finally, hooking it up via whichever cron mechanism you're using should finish the job.

Feb 16 2020

Setting sights on a new baseline

I haven't been completely idle for the past several years, for all that I've done a really bad job of writing new entries. One thing I've worked on during this time is learning a fair amount about Kubernetes, which (along with Docker) has been instrumental in popularizing Alpine Linux, a lightweight Linux distribution that focuses on security. When working with more of a service-oriented infrastructure instead of a monolithic one, keeping the overhead of virtual machines low leaves more resources for the actual services. Running services in containers also helps, but that's not a great approach for core services.

The standard Alpine Linux installation documentation covers all of the basics. A couple of additional minor notes:

  • I use the the Virtual image from the Downloads page, since I don't need to worry about a variety of hardware-related packages.
  • To be rid of the process '/sbin/getty -L 0 ttyS0 vt100' exited messages from /var/log/messages, I recommend commenting out this line from /etc/inittab (explanation provided here):
/etc/inittab
# enable login on alternative console
ttyS0::respawn:/sbin/getty -L 0 ttyS0 vt100
  • Installing open-vm-tools for ESXi integration comes down to a matter of personal taste. It registers information at boot-time, so starting the service immediately after installation doesn't update ESXi. So it's up to you if you think it's worth spending the 50MB of disk space for that.

I'm a proponent of having service users that are controlled centrally (in my case, via Active Directory). For Alpine Linux, since it doesn't natively use NSS (as it uses musl instead of glibc), integration comes in at the password authentication level via PAM, but not at the user verification level. This requires a little bit of extra work.

First off, install several packages after enabling the community repository:

$ apk add cyrus-sasl-gssapiv2 nss-pam-ldapd openssh-server-pam shadow]]

There's a bunch of documentation on how to set up nslcd on this Samba page, and how to set up the pam.d files on this nss-pam-ldapd page. The former is useful for how much detail it goes into for configuration, even if it's not on the main project site. In my case, I opt to go with the Kerberos authentication route, to avoid having the credentials left on the system in plaintext. If you're using Samba, running this on a domain controller should do the job:

$ samba-tool domain exportkeytab <keytab> --principal=<user>

This file then needs to be copied over to the client in question. For this purpose, that file on the client will be /etc/krb5.nslcd.keytab, with ownership by nslcd:nslcd and permissions 0600. After that, create an initial Kerberos ticket to work with for now (you'll need to figure out how to have it regularly renewed):

k5start isn't available on Alpine Linux by default. You can either build it yourself (fairly straightforward), follow the Samba username/password instructions, or wait for me to provide a package (in which k5start is configured as a service for automated renewal).

$ k5start -f /etc/krb5.nslcd.keytab -U -o nslcd -K 360 -b -k /tmp/nslcd.tkt

At this point, you can then make changes to /etc/nslcd.conf to hook up your directory server (most as per the Samba page, with some additional explanation for differences).

/etc/nslcd.conf
.
.
.
# We put both ldaps:// and ldap:// because they get used at slightly different times -
# ldap:// for querying the user details via the keytab, and ldaps:// for verifying the
# password. We put ldaps:// before ldap:// so that when verifying the password, the
# LDAP bind doesn't happen over cleartext.
uri ldaps://<LDAP server address>
uri ldap://<LDAP server address>

base <LDAP base>

# For the ldaps:// connection, don't blindly accept the certificate. Validate it.
tls_cacertfile <root certificate file>

pagesize 1000
referrals off
nss_nested_groups yes
sasl_mech GSSAPI
sasl_realm <Kerberos realm>
# nss-pam-ldapd is much happier being able to pass in the ticket's user.
sasl_authzid u:<user>
krb5_ccname /tmp/nslcd.tkt

# Uncomment the various "Mappings for Active Directory" lines.
.
.
.

You should be able to start the nslcd daemon and enable it on boot:

$ rc-service nslcd start
$ rc-update add nslcd

From here, in order to have PAM query nslcd, edit /etc/pam.d/base-auth to add the nss-pam-ldapd library:

/etc/pam.d/base-auth
# basic PAM configuration for Alpine.
auth    required        pam_env.so
auth    sufficient      pam_unix.so     nullok_secure
auth    required        pam_nologin.so  successok

auth    sufficient      pam_unix.so     nullok try_first_pass
auth    sufficient      pam_ldap.so     minimum_uid=1000 use_first_pass
# Required, since pam_unix.so has been downgraded from required to sufficient
auth    required        pam_deny.so

account required        pam_nologin.so
account sufficient      pam_unix.so
account sufficient      pam_ldap.so     minimum_uid=1000

password        sufficient      pam_unix.so     nullok sha512 shadow try_first_pass use_authtok
password        sufficient      pam_ldap.so     minimum_uid=1000 try_first_pass

-session        optional        pam_loginuid.so
-session        optional        pam_elogind.so
session sufficient      pam_unix.so
session optional        pam_ldap.so     minimum_uid=1000

Enabling OpenSSH logins from here is pretty simple:

/etc/ssh/sshd_config
.
.
.
UsePAM yes
.
.
.

As noted before, this is a PAM-only solution. As a result, any user that needs login capability will need a local user created, and that local user will dictate everything other than the password (e.g. the user ID, group ID, etc.). So ensure you do that for every user you need login permissions for (adjust options as you see fit):

$ useradd --create-home <user>

At this point, you should now be able to log in (via either console or ssh) to the system. Congratulations!

Note: Unfortunately, sudo won't work with your logged-in users, as it queries NSS by default, and the Alpine Linux version doesn't have LDAP-querying capabilities. So this is primarily useful for having distributed intermediate users.

Bonus! If you're interested in better SSH encryption, it's probably better not to use the defaults for sshd_config, since that current defaults (for a modern SSH client) to ecdsa-sha2-nistp256, which has some issues. As a result, it's worth thinking about adding this to the end of sshd_config (taken from this page). At present, the moduli file doesn't need to be adjusted since none of the primes are less than 2000 bits.

/etc/ssh/sshd_config
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
MACs [email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]

Nov 26 2017

Not quite dead yet

Yes, it's been a while since I've updated anything here. I really should do more updates. 😋 I've worked on a few things, so will start scribbling things here in the meantime.

At the moment, I'm replacing my older server at home with an Intel NUC. While doing so, I was looking at installing Windows Server on my server as before... except that a few things have changed. For starters, since it's a 7th Generation Intel Core-based system, Windows Server 2012 R2 is no longer supported. Okay, I can deal with that... except that my preferred minimal server interface is no longer supported. Thanks?

So I suppose I'll end up running VMware ESXi there too. Except that there have been changes there as well, with VMware 6.5, where the native Windows client has been deprecated. Thanks? And on top of that, predictably, ESXi doesn't support the 7th Gen NUC out of the box. Fortunately, there are workarounds, but... bleh.

Just can't win, I guess...

Aug 06 2016

First Looks: Windows Subsystem for Linux

As I imagine you've probably read about, the Windows 10 Anniversary Update included the Windows Subsystem for Linux (WSL). I don't fully understand the technical details, but I would imagine they've implemented something along the lines of the Linux emulation layer included in FreeBSD. There's still a fair amount I have to poke around with, but there are a few interesting things I've noticed so far:

  • There doesn't seem to be an obvious location of where the virtual filesystem is (although, admittedly, I haven't tried that hard to find where it is, and pico processes don't seem to be introspectable by Process Explorer). It doesn't appear to be in the usual Windows Store package location (%USERPROFILE%\AppData\Local\Packages). Each user does have their own instance of the filesystem, though, so it can't be used as a sharing mechanism. I suppose on the bright side, lxrun.exe lets you reset your WSL installation in case you break it.
  • WSL isn't able to run Windows executables, interestingly. So it looks like no scripting your Windows tools with a Linux stack.
  • Quite a few packages are installed by default. As of today, 434 (no visudo, though):
accountsservice-0.6.35-0ubuntu7.2
acpid-1:2.0.21-1ubuntu2
adduser-3.113+nmu3ubuntu3
apparmor-2.8.95~2430-0ubuntu5.3
apport-2.14.1-0ubuntu3.19
apport-symptoms-0.20
apt-1.0.1ubuntu2.11
apt-transport-https-1.0.1ubuntu2.11
apt-utils-1.0.1ubuntu2.11
apt-xapian-index-0.45ubuntu4
aptitude-0.6.8.2-1ubuntu4
aptitude-common-0.6.8.2-1ubuntu4
at-3.1.14-1ubuntu1
base-files-7.2ubuntu5.4
base-passwd-3.5.33
bash-4.3-7ubuntu1.5
bash-completion-1:2.1-4ubuntu0.1
bc-1.06.95-8ubuntu1
bind9-host-1:9.9.5.dfsg-3ubuntu0.8
bsdmainutils-9.0.5ubuntu1
bsdutils-1:2.20.1-5.1ubuntu20.7
busybox-initramfs-1:1.21.0-1ubuntu1
busybox-static-1:1.21.0-1ubuntu1
byobu-5.77-0ubuntu1.2
bzip2-1.0.6-5
ca-certificates-20160104ubuntu0.14.04.1
cloud-guest-utils-0.27-0ubuntu9.2
cloud-init-0.7.5-0ubuntu1.17
command-not-found-0.3ubuntu12
command-not-found-data-0.3ubuntu12
console-setup-1.70ubuntu8
coreutils-8.21-1ubuntu5.4
cpio-2.11+dfsg-1ubuntu1.2
cron-3.0pl1-124ubuntu2
cryptsetup-2:1.6.1-1ubuntu1
cryptsetup-bin-2:1.6.1-1ubuntu1
curl-7.35.0-1ubuntu2.6
dash-0.5.7-4ubuntu1
dbus-1.6.18-0ubuntu4.3
debconf-1.5.51ubuntu2
debconf-i18n-1.5.51ubuntu2
debianutils-4.4
dh-python-1.20140128-1ubuntu8.2
diffutils-1:3.3-1
dmidecode-2.12-2
dmsetup-2:1.02.77-6ubuntu2
dnsutils-1:9.9.5.dfsg-3ubuntu0.8
dosfstools-3.0.26-1
dpkg-1.17.5ubuntu5.5
e2fslibs:amd64-1.42.9-3ubuntu1.3
e2fsprogs-1.42.9-3ubuntu1.3
eatmydata-26-2
ed-1.9-2
eject-2.1.5+deb1+cvs20081104-13.1
ethtool-1:3.13-1
file-1:5.14-2ubuntu3.3
findutils-4.4.2-7
fonts-ubuntu-font-family-console-0.80-0ubuntu6
friendly-recovery-0.2.25
ftp-0.17-28
fuse-2.9.2-4ubuntu4.14.04.1
gawk-1:4.0.1+dfsg-2.1ubuntu2
gcc-4.8-base:amd64-4.8.4-2ubuntu1~14.04.1
gcc-4.9-base:amd64-4.9.3-0ubuntu4
gdisk-0.8.8-1ubuntu0.1
geoip-database-20140313-1
gettext-base-0.18.3.1-1ubuntu3
gir1.2-glib-2.0-1.40.0-1ubuntu0.2
gnupg-1.4.16-1ubuntu2.3
gpgv-1.4.16-1ubuntu2.3
grep-2.16-1
groff-base-1.22.2-5
gzip-1.6-3ubuntu1
hdparm-9.43-1ubuntu3
hostname-3.15ubuntu1
ifupdown-0.7.47.2ubuntu4.4
info-5.2.0.dfsg.1-2
init-system-helpers-1.14
initramfs-tools-0.103ubuntu4.2
initramfs-tools-bin-0.103ubuntu4.2
initscripts-2.88dsf-41ubuntu6.3
insserv-1.14.0-5ubuntu2
install-info-5.2.0.dfsg.1-2
iproute2-3.12.0-2ubuntu1
iptables-1.4.21-1ubuntu1
iputils-ping-3:20121221-4ubuntu1.1
iputils-tracepath-3:20121221-4ubuntu1.1
irqbalance-1.0.6-2ubuntu0.14.04.4
isc-dhcp-client-4.2.4-7ubuntu12.4
isc-dhcp-common-4.2.4-7ubuntu12.4
iso-codes-3.52-1
kbd-1.15.5-1ubuntu1
keyboard-configuration-1.70ubuntu8
klibc-utils-2.0.3-0ubuntu1
kmod-15-0ubuntu6
krb5-locales-1.12+dfsg-2ubuntu5.2
landscape-client-14.12-0ubuntu0.14.04
landscape-common-14.12-0ubuntu0.14.04
language-pack-en-1:14.04+20160720
language-pack-en-base-1:14.04+20160720
language-selector-common-0.129.3
laptop-detect-0.13.7ubuntu2
less-458-2
libaccountsservice0:amd64-0.6.35-0ubuntu7.2
libacl1:amd64-2.2.52-1
libapparmor-perl-2.8.95~2430-0ubuntu5.3
libapparmor1:amd64-2.8.95~2430-0ubuntu5.3
libapt-inst1.5:amd64-1.0.1ubuntu2.11
libapt-pkg4.12:amd64-1.0.1ubuntu2.11
libarchive-extract-perl-0.70-1
libasn1-8-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libasprintf0c2:amd64-0.18.3.1-1ubuntu3
libattr1:amd64-1:2.4.47-1ubuntu1
libaudit-common-1:2.3.2-2ubuntu1
libaudit1:amd64-1:2.3.2-2ubuntu1
libbind9-90-1:9.9.5.dfsg-3ubuntu0.8
libblkid1:amd64-2.20.1-5.1ubuntu20.7
libboost-iostreams1.54.0:amd64-1.54.0-4ubuntu3.1
libbsd0:amd64-0.6.0-2ubuntu1
libbz2-1.0:amd64-1.0.6-5
libc-bin-2.19-0ubuntu6.7
libc6:amd64-2.19-0ubuntu6.7
libcap-ng0-0.7.3-1ubuntu2
libcap2:amd64-1:2.24-0ubuntu2
libcap2-bin-1:2.24-0ubuntu2
libcgmanager0:amd64-0.24-0ubuntu7.5
libck-connector0:amd64-0.4.5-3.1ubuntu2
libclass-accessor-perl-0.34-1
libcomerr2:amd64-1.42.9-3ubuntu1.3
libcryptsetup4-2:1.6.1-1ubuntu1
libcurl3:amd64-7.35.0-1ubuntu2.6
libcurl3-gnutls:amd64-7.35.0-1ubuntu2.6
libcwidget3-0.5.16-3.5ubuntu1
libdb5.3:amd64-5.3.28-3ubuntu3
libdbus-1-3:amd64-1.6.18-0ubuntu4.3
libdbus-glib-1-2:amd64-0.100.2-1
libdebconfclient0:amd64-0.187ubuntu1
libdevmapper1.02.1:amd64-2:1.02.77-6ubuntu2
libdns100-1:9.9.5.dfsg-3ubuntu0.8
libdrm2:amd64-2.4.64-1~ubuntu14.04.1
libdumbnet1-1.12-4build1
libedit2:amd64-3.1-20130712-2
libelf1:amd64-0.158-0ubuntu5.2
libept1.4.12:amd64-1.0.12
libestr0-0.1.9-0ubuntu2
libevent-2.0-5:amd64-2.0.21-stable-1ubuntu1.14.04.1
libexpat1:amd64-2.1.0-4ubuntu1.1
libffi6:amd64-3.1~rc1+r3.0.13-12ubuntu0.1
libfreetype6:amd64-2.5.2-1ubuntu2.5
libfribidi0:amd64-0.19.6-1
libfuse2:amd64-2.9.2-4ubuntu4.14.04.1
libgc1c2:amd64-1:7.2d-5ubuntu2
libgcc1:amd64-1:4.9.3-0ubuntu4
libgck-1-0:amd64-3.10.1-1
libgcr-3-common-3.10.1-1
libgcr-base-3-1:amd64-3.10.1-1
libgcrypt11:amd64-1.5.3-2ubuntu4.3
libgdbm3:amd64-1.8.3-12build1
libgeoip1:amd64-1.6.0-1
libgirepository-1.0-1-1.40.0-1ubuntu0.2
libglib2.0-0:amd64-2.40.2-0ubuntu1
libglib2.0-data-2.40.2-0ubuntu1
libgnutls-openssl27:amd64-2.12.23-12ubuntu2.5
libgnutls26:amd64-2.12.23-12ubuntu2.5
libgpg-error0:amd64-1.12-0.2ubuntu1
libgpm2:amd64-1.20.4-6.1
libgssapi-krb5-2:amd64-1.12+dfsg-2ubuntu5.2
libgssapi3-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libhcrypto4-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libheimbase1-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libheimntlm0-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libhx509-5-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libicu52:amd64-52.1-3ubuntu0.4
libidn11:amd64-1.28-1ubuntu2
libio-string-perl-1.08-3
libisc95-1:9.9.5.dfsg-3ubuntu0.8
libisccc90-1:9.9.5.dfsg-3ubuntu0.8
libisccfg90-1:9.9.5.dfsg-3ubuntu0.8
libjson-c2:amd64-0.11-3ubuntu1.2
libjson0:amd64-0.11-3ubuntu1.2
libk5crypto3:amd64-1.12+dfsg-2ubuntu5.2
libkeyutils1:amd64-1.5.6-1
libklibc-2.0.3-0ubuntu1
libkmod2:amd64-15-0ubuntu6
libkrb5-26-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libkrb5-3:amd64-1.12+dfsg-2ubuntu5.2
libkrb5support0:amd64-1.12+dfsg-2ubuntu5.2
libldap-2.4-2:amd64-2.4.31-1+nmu2ubuntu8.2
liblocale-gettext-perl-1.05-7build3
liblockfile-bin-1.09-6ubuntu1
liblockfile1:amd64-1.09-6ubuntu1
liblog-message-simple-perl-0.10-1
liblwres90-1:9.9.5.dfsg-3ubuntu0.8
liblzma5:amd64-5.1.1alpha+20120614-2ubuntu2
libmagic1:amd64-1:5.14-2ubuntu3.3
libmodule-pluggable-perl-5.1-1
libmount1:amd64-2.20.1-5.1ubuntu20.7
libmpdec2:amd64-2.4.0-6
libncurses5:amd64-5.9+20140118-1ubuntu1
libncursesw5:amd64-5.9+20140118-1ubuntu1
libnewt0.52:amd64-0.52.15-2ubuntu5
libnfnetlink0:amd64-1.0.1-2
libnih-dbus1:amd64-1.0.3-4ubuntu25
libnih1:amd64-1.0.3-4ubuntu25
libnuma1:amd64-2.0.9~rc5-1ubuntu3.14.04.2
libp11-kit0:amd64-0.20.2-2ubuntu2
libpam-cap:amd64-1:2.24-0ubuntu2
libpam-modules:amd64-1.1.8-1ubuntu2.2
libpam-modules-bin-1.1.8-1ubuntu2.2
libpam-runtime-1.1.8-1ubuntu2.2
libpam-systemd:amd64-204-5ubuntu20.18
libpam0g:amd64-1.1.8-1ubuntu2.2
libparse-debianchangelog-perl-1.2.0-1ubuntu1
libparted0debian1:amd64-2.3-19ubuntu1.14.04.1
libpcap0.8:amd64-1.5.3-2
libpci3:amd64-1:3.2.1-1ubuntu5.1
libpcre3:amd64-1:8.31-2ubuntu2.1
libpipeline1:amd64-1.3.0-1
libplymouth2:amd64-0.8.8-0ubuntu17.1
libpng12-0:amd64-1.2.50-1ubuntu2.14.04.2
libpod-latex-perl-0.61-1
libpolkit-agent-1-0:amd64-0.105-4ubuntu3.14.04.1
libpolkit-backend-1-0:amd64-0.105-4ubuntu3.14.04.1
libpolkit-gobject-1-0:amd64-0.105-4ubuntu3.14.04.1
libpopt0:amd64-1.16-8ubuntu1
libprocps3:amd64-1:3.3.9-1ubuntu2.2
libpython-stdlib:amd64-2.7.5-5ubuntu3
libpython2.7:amd64-2.7.6-8ubuntu0.2
libpython2.7-minimal:amd64-2.7.6-8ubuntu0.2
libpython2.7-stdlib:amd64-2.7.6-8ubuntu0.2
libpython3-stdlib:amd64-3.4.0-0ubuntu2
libpython3.4-minimal:amd64-3.4.3-1ubuntu1~14.04.3
libpython3.4-stdlib:amd64-3.4.3-1ubuntu1~14.04.3
libreadline6:amd64-6.3-4ubuntu2
libroken18-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
librtmp0:amd64-2.4+20121230.gitdf6c518-1
libsasl2-2:amd64-2.1.25.dfsg1-17build1
libsasl2-modules:amd64-2.1.25.dfsg1-17build1
libsasl2-modules-db:amd64-2.1.25.dfsg1-17build1
libselinux1:amd64-2.2.2-1ubuntu0.1
libsemanage-common-2.2-1
libsemanage1:amd64-2.2-1
libsepol1:amd64-2.2-1ubuntu0.1
libsigc++-2.0-0c2a:amd64-2.2.10-0.2ubuntu2
libsigsegv2:amd64-2.10-2
libslang2:amd64-2.2.4-15ubuntu1
libsqlite3-0:amd64-3.8.2-1ubuntu2.1
libss2:amd64-1.42.9-3ubuntu1.3
libssl1.0.0:amd64-1.0.1f-1ubuntu2.18
libstdc++6:amd64-4.8.4-2ubuntu1~14.04.1
libsub-name-perl-0.05-1build4
libsystemd-daemon0:amd64-204-5ubuntu20.18
libsystemd-login0:amd64-204-5ubuntu20.18
libtasn1-6:amd64-3.4-3ubuntu0.3
libterm-ui-perl-0.42-1
libtext-charwidth-perl-0.04-7build3
libtext-iconv-perl-1.7-5build2
libtext-soundex-perl-3.4-1build1
libtext-wrapi18n-perl-0.06-7
libtimedate-perl-2.3000-1
libtinfo5:amd64-5.9+20140118-1ubuntu1
libudev1:amd64-204-5ubuntu20.18
libusb-0.1-4:amd64-2:0.1.12-23.3ubuntu1
libusb-1.0-0:amd64-2:1.0.17-1ubuntu2
libustr-1.0-1:amd64-1.0.4-3ubuntu2
libuuid1:amd64-2.20.1-5.1ubuntu20.7
libwind0-heimdal:amd64-1.6~git20131207+dfsg-1ubuntu1.1
libwrap0:amd64-7.6.q-25
libx11-6:amd64-2:1.6.2-1ubuntu2
libx11-data-2:1.6.2-1ubuntu2
libxapian22-1.2.16-2ubuntu1
libxau6:amd64-1:1.0.8-1
libxcb1:amd64-1.10-2ubuntu1
libxdmcp6:amd64-1:1.1.1-1
libxext6:amd64-2:1.3.2-1ubuntu0.0.14.04.1
libxml2:amd64-2.9.1+dfsg1-3ubuntu4.7
libxmuu1:amd64-2:1.1.1-1
libxtables10-1.4.21-1ubuntu1
libyaml-0-2:amd64-0.1.4-3ubuntu3.1
locales-2.13+git20120306-12.1
lockfile-progs-0.1.17
login-1:4.1.5.1-1ubuntu9.2
logrotate-3.8.7-1ubuntu1
lsb-base-4.1+Debian11ubuntu6
lsb-release-4.1+Debian11ubuntu6
lshw-02.16-2ubuntu1.3
lsof-4.86+dfsg-1ubuntu2
ltrace-0.7.3-4ubuntu5.1
makedev-2.3.1-93ubuntu1
man-db-2.6.7.1-1ubuntu1
manpages-3.54-1ubuntu1
mawk-1.3.3-17ubuntu2
mime-support-3.54ubuntu1.1
mlocate-0.26-1ubuntu1
module-init-tools-15-0ubuntu6
mount-2.20.1-5.1ubuntu20.7
mountall-2.53
mtr-tiny-0.85-2
multiarch-support-2.19-0ubuntu6.7
nano-2.2.6-1ubuntu1
ncurses-base-5.9+20140118-1ubuntu1
ncurses-bin-5.9+20140118-1ubuntu1
ncurses-term-5.9+20140118-1ubuntu1
net-tools-1.60-25ubuntu2.1
netbase-5.2
netcat-openbsd-1.105-7ubuntu1
ntfs-3g-1:2013.1.13AR.1-2ubuntu2
ntpdate-1:4.2.6.p5+dfsg-3ubuntu2.14.04.8
open-vm-tools-2:9.4.0-1280544-5ubuntu6.2
openssh-client-1:6.6p1-2ubuntu2.6
openssh-server-1:6.6p1-2ubuntu2.6
openssh-sftp-server-1:6.6p1-2ubuntu2.6
openssl-1.0.1f-1ubuntu2.18
os-prober-1.63ubuntu1.1
overlayroot-0.25ubuntu1.14.04.1
parted-2.3-19ubuntu1.14.04.1
passwd-1:4.1.5.1-1ubuntu9.2
patch-2.7.1-4ubuntu2.3
pciutils-1:3.2.1-1ubuntu5.1
perl-5.18.2-2ubuntu1.1
perl-base-5.18.2-2ubuntu1.1
perl-modules-5.18.2-2ubuntu1.1
plymouth-0.8.8-0ubuntu17.1
plymouth-theme-ubuntu-text-0.8.8-0ubuntu17.1
policykit-1-0.105-4ubuntu3.14.04.1
pollinate-4.7-0ubuntu1.4
popularity-contest-1.57ubuntu1
powermgmt-base-1.31build1
ppp-2.4.5-5.1ubuntu2.2
pppconfig-2.3.19ubuntu1
pppoeconf-1.20ubuntu1
procps-1:3.3.9-1ubuntu2.2
psmisc-22.20-1ubuntu2
python-2.7.5-5ubuntu3
python-apt-0.9.3.5ubuntu2
python-apt-common-0.9.3.5ubuntu2
python-chardet-2.0.1-2build2
python-cheetah-2.4.4-3.fakesyncbuild1
python-configobj-4.7.2+ds-5build1
python-debian-0.1.21+nmu2ubuntu2
python-gdbm-2.7.5-1ubuntu1
python-json-pointer-1.0-2build1
python-jsonpatch-1.3-4
python-minimal-2.7.5-5ubuntu3
python-oauth-1.0.1-3build2
python-openssl-0.13-2ubuntu6
python-pam-0.4.2-13.1ubuntu3
python-pkg-resources-3.3-1ubuntu2
python-prettytable-0.7.2-2ubuntu2
python-pycurl-7.19.3-0ubuntu3
python-requests-2.2.1-1ubuntu0.3
python-serial-2.6-1build1
python-six-1.5.2-1ubuntu1
python-twisted-bin-13.2.0-1ubuntu1
python-twisted-core-13.2.0-1ubuntu1
python-twisted-names-13.2.0-1ubuntu1
python-twisted-web-13.2.0-1ubuntu1
python-urllib3-1.7.1-1ubuntu4
python-xapian-1.2.16-2ubuntu1
python-yaml-3.10-4ubuntu0.1
python-zope.interface-4.0.5-1ubuntu4
python2.7-2.7.6-8ubuntu0.2
python2.7-minimal-2.7.6-8ubuntu0.2
python3-3.4.0-0ubuntu2
python3-apport-2.14.1-0ubuntu3.19
python3-apt-0.9.3.5ubuntu2
python3-commandnotfound-0.3ubuntu12
python3-dbus-1.2.0-2build2
python3-distupgrade-1:0.220.8
python3-gdbm:amd64-3.4.3-1~14.04.2
python3-gi-3.12.0-1ubuntu1
python3-minimal-3.4.0-0ubuntu2
python3-newt-0.52.15-2ubuntu5
python3-problem-report-2.14.1-0ubuntu3.19
python3-pycurl-7.19.3-0ubuntu3
python3-software-properties-0.92.37.7
python3-update-manager-1:0.196.14
python3.4-3.4.3-1ubuntu1~14.04.3
python3.4-minimal-3.4.3-1ubuntu1~14.04.3
readline-common-6.3-4ubuntu2
resolvconf-1.69ubuntu1.1
rsync-3.1.0-2ubuntu0.2
rsyslog-7.4.4-1ubuntu2.6
run-one-1.17-0ubuntu1
screen-4.1.0~20120320gitdb59704-9
sed-4.2.2-4ubuntu1
sensible-utils-0.0.9
sgml-base-1.26+nmu4ubuntu1
shared-mime-info-1.2-0ubuntu3
software-properties-common-0.92.37.7
ssh-import-id-3.21-0ubuntu1
strace-4.8-1ubuntu5
sudo-1.8.9p5-1ubuntu1.2
systemd-services-204-5ubuntu20.18
systemd-shim-6-2bzr1
sysv-rc-2.88dsf-41ubuntu6.3
sysvinit-utils-2.88dsf-41ubuntu6.3
tar-1.27.1-1
tasksel-2.88ubuntu15
tasksel-data-2.88ubuntu15
tcpd-7.6.q-25
tcpdump-4.5.1-2ubuntu1.2
telnet-0.17-36build2
time-1.7-24
tmux-1.8-5
tzdata-2016b-0ubuntu0.14.04
ubuntu-keyring-2012.05.19
ubuntu-minimal-1.325
ubuntu-release-upgrader-core-1:0.220.8
ubuntu-standard-1.325
ucf-3.0027+nmu1
udev-204-5ubuntu20.18
ufw-0.34~rc-0ubuntu2
unattended-upgrades-0.82.1ubuntu2.4
update-manager-core-1:0.196.14
update-notifier-common-0.154.1ubuntu1
upstart-1.12.1-0ubuntu4.2
ureadahead-0.100.0-16
usbutils-1:007-2ubuntu1.1
util-linux-2.20.1-5.1ubuntu20.7
uuid-runtime-2.20.1-5.1ubuntu20.7
vim-2:7.4.052-1ubuntu3
vim-common-2:7.4.052-1ubuntu3
vim-runtime-2:7.4.052-1ubuntu3
vim-tiny-2:7.4.052-1ubuntu3
w3m-0.5.3-15
wget-1.15-1ubuntu1.14.04.1
whiptail-0.52.15-2ubuntu5
xauth-1:1.0.7-1ubuntu1
xkb-data-2.10.1-1ubuntu1
xml-core-0.13+nmu2
xz-utils-5.1.1alpha+20120614-2ubuntu2
zerofree-1.0.2-1ubuntu1

Jun 28 2016

1Password for Families

So I've been using KeePass for a while to manage my credentials. Somewhat recently, there was a kerfuffle involving an unencrypted check for updates. It wasn't so much that there was an issue that bothered me (everything has issues, including security software). What bothered me was the complete disregard for it as an issue, particularly since it's meant to be a piece of security software.

So what came up next was 1Password for Families, since I had a sibling who decided to go for it and let me opt in as well. Seeing as it's a commercial product that's been out for a while, you would think that they have it to the point where It Just Works, right?

Wrong.

  • The import process was fairly miserable. Sure, I understand that KeePass might not be a large target audience. But when their migration solution involves running a Perl script? I suppose ignoring Windows might be a strategy, but it doesn't strike me as a good one.
  • Once the import was complete, I tried to import the generated file. Like a good number of Windows users, I'm now on Windows 10... except the Windows store version of the app (required for Families) doesn't support imports. I guess Windows + Families users don't matter....
  • I ended up using a Mac OS X system to do the import. Almost every entry came in as a Login, which isn't a huge issue. Except that they, as a design decision, opted to not allow for converting between categories. I have almost 600 entries, and manually recreating those items isn't a pleasant option.
  • I have several items with attachments (e.g. 2FA where I've saved off the authenticator image so that I can have multiple synced authenticators). Except those aren't supported in Families; again, a design decision.
  • For a product that was initially built around saving off website credentials (like most of these applications), you would think that they would at least have that working great out of the gate. Except you'd be wrong, at least for Windows. For the current official releases, the browser plugins require the standard desktop application... that doesn't support Families. In somewhat fairness, the 1Password 6 beta adds support for this... almost six months after they launched Families.

Short version? Families (and likely Teams as well) was launched half-assed. Windows is a low priority for them (seeing as one of the most important features wasn't provided for half a year). Dealing with a product like this just doesn't make sense, so I'm going back to my usage of KeePass, where at least I know what to expect.

Jan 10 2016

More fun (or not) with VPN

So I had initially written about setting up VPN with Windows Server as the platform. But I then swapped over to Libreswan and Linux. Ironic or not, I've decided to switch back to using Windows Server for a couple of reasons:

  • It turns out that the problems I was having with routing were actually the fault of my personal wireless router, and not the platform. Switching to a custom firmware and setting my custom route there was actually necessary to get Libreswan/Linux working as well.
  • Debugging the Libreswan/Linux setup is easier, true. But only nominally so. And in return, the setup is considerably more complicated.
  • Perhaps most importantly, under the Libreswan/Linux setup, a given user could only have a single connection to the VPN. Under Windows Server, that restriction doesn't exist.

However, during that process, I also decided to switch around my home setup. Previously, I was running a domain controller as a Hyper-V host with a RRAS server as a client. The problem is that since the RRAS client comes up after the domain controller does, so it doesn't always act correctly as a result. So, I decided to switch it around, and try to set up a RRAS server as the Hyper-V host, with the domain controller as a client. Except... this doesn't work properly. Honestly, I'm somewhat shocked that this bug has existed for over 3 years - I will admit that's one area where open source would (probably) not have let this bug live for this long. In this case, it resulted in me setting up a standalone Hyper-V host with two clients: the RRAS server coming up first, with the domain controller coming up later. sigh<

Update (1/19/2016): So after kicking it around some more, I still haven't managed to get my site-to-site set up quite the way I want. Even following Microsoft's IKEv2 troubleshooting page, I can't manage to make it work. The only way I've managed to get it to work is for my colocated server to specify my home server via IP and with a PSK. Even after setting up a custom certificate template with the appropriate EKUs and create the associate templates, it's a no-go - all I get is a RemoteAccess error in the Event Viewer with Event ID 20111 ("IKE authentication credentials are unacceptable"). Very unhelpful, and this is one of the areas where Windows' ability to debug can be nigh-nonexistent. But, on the other hand, iOS is able to connect just fine. Yay?

Jun 18 2015

CentOS 7: Differences on the ground floor

As you might expect, CentOS 7 has its package differences from CentOS 6. What does looks like from the ground, though? There have been a number of changes, as you might expect.

Well, let's start with my base-level kickstart file which sets up a fairly minimal system:

Kickstart file
#version=RHEL7

# Standard CentOS kickstart configuration.

authconfig --enableshadow --passalgo=sha512

install
reboot
eula --agreed
# Since we want to install packages that aren't on the minimal disc, we can't actually install from the disc. We can't
# specify additional repo entries that are Base, as they get ignored (name collision).
url --mirrorlist=http://mirrorlist.centos.org/?release=7&amp;arch=x86_64&amp;repo=os

firewall --enabled --service=ssh
firstboot --disable

ignoredisk --only-use=sda,sdb,sdc

keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8

network --bootproto dhcp --device=eth0 --noipv6
repo --name=Base --mirrorlist=http://mirrorlist.centos.org/?release=7&amp;arch=x86_64&amp;repo=os --cost=100
repo --name=Updates --mirrorlist=http://mirrorlist.centos.org/?release=7&amp;arch=x86_64&amp;repo=updates --cost=90

rootpw --iscrypted __PASSWORD_HASH_GOES_HERE__
selinux --enforcing
services --enabled="chronyd"
timezone --utc America/Los_Angeles --isUtc
bootloader --append="rhgb quiet crashkernel=auto" --location=mbr --driveorder="sda,sdb,sdc" --boot-drive=sda

zerombr
clearpart --all --initlabel
part /boot --fstype=ext4 --size=128 --ondrive=sda
part swap --size=256 --ondrive=sda
part / --fstype=ext4 --grow --ondrive=sda
part /var --fstype=ext4 --grow --ondrive=sdb
part /tmp --fstype=ext4 --grow --ondrive=sdc

%packages --nobase
@core

# No need for Adaptec drivers.
-aic94xx-firmware

# No need for sound drivers.
-alsa-*

# No need for firmware loaders.
-fxload

# No need for IBM Power Linux RAID drivers.
-iprutils

# No need for PVR drivers.
-ivtv-firmware

# No need for wireless drivers.
-iwl*-firmware
-NetworkManager*
-wpa_supplicant

# No need for Infiniband drivers.
-rdma

# No need for network teaming.
-jansson
-libnl3
-libnl3-cli
-libteam
-teamd

# No need for virtualization utilities
-tuned
-virt-what

# VMware kernel compilation requirements.
gcc
kernel-headers

# Useful utilities.
deltarpm
man
rsync
%end

%pre
%end

%post
# Declare that the disks don't support SMART.
/bin/cat /etc/tempfiles.d/disable_smart.conf <<EOF
w /sys/devices/pci0000:00/0000:00:15.0/0000:03:00.0/host2/port-2:0/end_device-2:0/target2:0:0/2:0:0:0/scsi_disk/2:0:0:0/max_write_same_blocks - - - - 0
w /sys/devices/pci0000:00/0000:00:15.0/0000:03:00.0/host2/port-2:1/end_device-2:1/target2:0:1/2:0:1:0/scsi_disk/2:0:1:0/max_write_same_blocks - - - - 0
w /sys/devices/pci0000:00/0000:00:15.0/0000:03:00.0/host2/port-2:2/end_device-2:2/target2:0:2/2:0:2:0/scsi_disk/2:0:2:0/max_write_same_blocks - - - - 0
EOF

%end

Naturally, if you're going to use this as a template, you would make changes as appropriate to your own system (particularly, I'd imagine, the disk configuration).

A couple of notes:

  • You may notice that I don't do much in the way of system configuration here. That's because it makes more sense to use a configuration management tool to configure systems, so the base kickstart configuration file tries to target system-level stuff.
  • I use a multi-partition layout to "sandbox" the partitions that have a potential to grow out of control. I don't want /var or /tmp filling up to bring the entire system down. As a bonus, since this is a virtualized system, this allows me to grow the three partitions as needed relatively easily (since they're all located at the end of their respective disks).
  • This is a base kickstart configuration, so other derived configurations will naturally have additional packages and post-install instructions.

Packages that have been removed from CentOS 7 (notes sometimes pulled from this page):

 Removed packages 
 Package  Note
 attr  
 b43-openfwwf  
 bzip2  
 checkpolicy  
 cloog-ppl  
 coreutils-libs  
 cyrus-sasl  
 dash  Looks like CentOS gave up on the dash experiment.
 db4  → libdb
 db4-utils  → libdb-utils
 dracut-kernel → dracut
 efibootmgr 
 gamin  
 groff  → groff-base
 grub  → grub2, grub2-tools
 iptables-ipv6  
 kernel-firmware  → linux-firmware
 libnih  
 libudev  
 libusb  
 m4  
 MAKEDEV  
 man  → man-db
 mingetty  → util-linux
 module-init-tools  
 mysql-libs  → mariadb-libs
 net-tools  
 perl-Module-Pluggable  
 perl-version  
 ppl  
 procps  → procps-ng
 psmisc  
 system-config-firewall-base  → firewalld
 udev  
 upstart  
 util-linux-ng  → util-linux
 xz-lzma-compat  
 yum-presto  

Meanwhile, the number of added packages is fairly considerable:

 Added packages 
 Package  Note
 authconfig  
 bind-libs-lite  
 bind-license  
 biosdevname  
 btrfs-progs  Mmm... btrfs.
 centos-logos  ← redhat-logos
 chrony  
 cryptsetup-libs  
 dbus  
 dbus-python  
 dhcp-libs  
 dracut-config-rescue  
 dracut-network  
 ebtables  Required by firewalld.
 elfutils-libs  
 firewalld  ← system-config-firewall-base
 freetype  Required by grub2.
 gettext  
 gettext-libs  
 gobject-introspection  
 groff-base  ← groff
 grub2  ← grub
 grub2-tools  ← grub
 hardlink  
 hostname  
 irqbalance  
 json-c  
 kbd-legacy  
 kernel-devel  
 kernel-tools  
 kernel-tools-libs  
 kexec-tools  
 kmod  
 kmod-libs  
 kpartx  
 libassuan  
 libcroco  
 libdaemon  
 libdb  ← db4
 libdb-utils  ← db4-utils
 libestr  
 libmnl  
 libmount  
 libmpc  
 libnetfilter_conntrack  
 libnfnetlink  
 libpipeline  
 libpwquality  
 libselinux-python  
 libsysfs  
 libunistring  
 libverto  
 linux-firmware  ← kernel-firmware
 lzo  
 man-db  ← man
 mariadb-libs  ← mysql-libs
 microcode_ctl  
 newt-python  
 numactl-libs  
 openssl-libs  
 os-prober  
 perl-Carp  
 perl-constant  
 perl-Encode  
 perl-Exporter  
 perl-File-Path  
 perl-File-Temp  
 perl-Filter  
 perl-Getopt-Long  
 perl-HTTP-Tiny  
 perl-macros  
 perl-parent  
 perl-PathTools  
 perl-podlators  
 perl-Pod-Perldoc  
 perl-Pod-Usage  
 perl-Scalar-List-Utils  
 perl-Socket  
 perl-Storable  
 perl-Text-ParseWords  
 perl-threads  
 perl-threads-shared  
 perl-Time-HiRes  
 perl-Time-Local  
 procps-ng  ← procps
 pygobject3-base  
 pyliblzma  
 python-decorator  
 python-slip  
 python-slip-dbus  
 pyxattr  
 qrencode-libs  
 rpm-build-libs  
 snappy  
 systemd  CentOS 7 moves away from Sys V-style daemon management.
 systemd-libs  
 systemd-sysv  
 util-linux  ← util-linux-ng
 xfsprogs  

Disk usage is comparable to CentOS 6, even with the additional packages (many of which I expect are a result of refactoring). And several of those new packages will require further investigation, to see how well the new functionality works.

Jun 18 2015

Kickstarting a new image

I've decided to finally get around to set up kickstart configuration files for my system images, since I've started investigating migrating over to CentOS 7. Kickstart, if you're not familiar with it, is a method of automating Linux installation and configuration, and is largely centered around the Red Hat-based distributions. While I was setting all of this up, I decided to also investigate whether it was worth switching from CentOS to Ubuntu Server, seeing as Ubuntu usage has passed CentOS and RHEL usage according to W3Techs (I suppose I could have looked at Debian as well, but for whatever reason it doesn't particularly appeal to me - possibly because it's not as marketable a job skill, for all that I don't really do this for a career?).

That said, I decided not to, for a couple of reasons:

  • The difference in how well they're documented is huge. Red Hat has a tremendous amount of documentation on setting up a kickstart installation compared to Ubuntu's preseed documentation (which seems to boil down to: take this undocumented file and it should work). Somewhat ironically, Debian has considerably better documentation.
  • Red Hat's installation process generates a kickstart configuration file (/root/anaconda-ks.cfg) that you can immediately turn around and feed back into a kickstart installation to get the same result, whereas the Debian documentation notes that their equivalent (debconf-get-selections --installer; debconf-get-selections) doesn't actually quite work (and I would expect that Ubuntu would follow in the same footsteps).
  • And, of course, I'm still better and more comfortable with Red Hat-based distributions than Ubuntu distributions, which matters for what is effectively a production deployment.

P.S. Yes, Ubuntu can also support kickstart installations, but it's a hacky process. I don't care that much.

Sep 01 2014

Tunnelling through the Internet

As mentioned in the previous post, I'm writing down some details concerning setting up a VPN, which can occasionally be quite useful, whether it be due to accessing the Internet from an insecure location or due to working around region restrictions. As before, I'm using Libreswan, along with xl2tpd and ppp. I'm also using winbind (part of the Samba project) in order to authenticate against a Windows domain.

VPN

Bits and pieces taken from this page.

As with the subnet-to-subnet configuration, you'll need to put the Libreswan repository file in /etc/yum.repos.d, put the the Libreswan GPG key in /etc/pki/rpm-gpg, and install the Fedora Extra Packages for Enterprise Linux 6 RPM. At this point, you can install the packages you need to move forward:

$ yum install libreswan xl2tpd ppp

There are more moving pieces this time through, so the configuration is a bit more involved. Our example uses the following assumptions:

192.168.0.0/24: internal network
1.2.3.4: external network IP
192.168.0.1: internal network IP
192.168.0.200: internal network DNS IP
192.168.0.90-192.168.0.99: IP range for VPN clients
eth0: external-facing network adapter
eth1: internal-facing network adapter

Libreswan

Configure /etc/ipsec.conf as noted in the previous article. We'll set up another configuration file for the dialin VPN, /etc/ipsec.d/dialin.conf. For the sake of simplicity (and compatibility), we'll do a pre-shared key (PSK) configuration:

/etc/ipsec.d/dialin.conf
conn dialin
       # We're using a PSK for now.
       authby=secret
       # Add the VPN type, but don't start it (since clients will be initiating connections).
       auto=add
       forceencaps=yes
       ike_frag=yes
       # The outside-facing IP.
       left=1.2.3.4
       leftid=@left.internal
       leftsubnet=0.0.0.0/0
       right=%any
       rightsubnet=0.0.0.0/0
       # The internal DNS server's IP.
       modecfgdns1=192.168.0.100
       modecfgpull=yes
       pfs=no
       rekey=no

To define the PSK, create /etc/ipsec.d/dialin.secrets:

/etc/ipsec.d/dialin.secrets
# As before, the outside-facing IP. Also, change the PSK to something considerably better than this.
1.2.3.4  %any  :  PSK "pre-shared key"

As before, you can be paranoid with the secrets file:

$ chown root:root /etc/ipsec.d/*.secrets
$ chmod 0600 /etc/ipsec.d/*.secrets

And the same additional lines to /etc/sysctl.conf apply here:

/etc/sysctl.conf
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

Along with the verification step:

$ ipsec verify

xl2tpd/ppp

xl2tpd and ppp are intertwined, so their configuration happens pretty much at the same time. Set up your /etc/xl2tpd/xl2tpd.conf roughly as follows, adjusting for the configuration above:

/etc/xl2tpd/xl2tpd.conf
[global]
listen-addr = 1.2.3.4

[lns default]
ip range = 192.168.0.90-192.168.0.99
local ip = 192.168.0.1
require chap = yes
refuse pap = yes
require authentication = yes
name = l2tpd
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

For now, set up /etc/ppp/options.xl2tpd as follows:

/etc/ppp/options.xl2tpd
ipcp-accept-local
ipcp-accept-remote
ms-dns 192.168.0.200
noccp
auth
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
lock
proxyarp
connect-delay 5000

Set up usernames and passwords in /etc/ppp/chap-secrets, one per line (replace $username and $password as appropriate):

/etc/ppp/chap-secrets
$username l2tpd "$password" *

iptables

As before, there need to be additional entries in the iptables configuration:

iptables
# Set up an ICMP bucket.
-N ICMPALL
# Set up a rejection bucket.
-N ZREJ

# Using connection tracking, accept packets we already know about.
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Trust the local network; you can choose to have more restrictive rules than this.
-A INPUT -i eth1 -j ACCEPT
-A INPUT -i ppp+ -j ACCEPT
-A FORWARD -i eth1 -j ACCEPT
-A FORWARD -i ppp+ -j ACCEPT

# Treat ICMP packets specially.
-A INPUT -p icmp -m icmp --icmp-type any -j ICMPALL

# Allow new connections to be made to ports 500 (IKE) and 4500 (IKE NAT-Traversal), both for Libreswan.
-A INPUT -p udp -m conntrack --ctstate NEW -m multiport --dports 500,4500 -j ACCEPT

# Allow connections to port 1701 (L2TP) for Libreswan.
-A INPUT -p udp -m udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
-A INPUT -p udp -m udp --dport 1701 -j DROP

# Goes at the bottom of the INPUT section: reject all other packets.
-A INPUT -j ZREJ

# Only forward connections we know about from the "outside" to the "inside," using built-in connection tracking.
-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Forward valid IPsec packets.
-A FORWARD -m policy --dir in --pol ipsec -j ACCEPT

# Goes at the bottom of the FORWARD section: reject all other packets.
-A FORWARD -j ZREJ

# Reject fragmented packets.
-A ICMPALL -p icmp -f -j DROP
# Accept: echo reply
-A ICMPALL -p icmp -m icmp --icmp-type 0 -j ACCEPT
# Accept: destination unreachable
-A ICMPALL -p icmp -m icmp --icmp-type 3 -j ACCEPT
# Accept: source quench
-A ICMPALL -p icmp -m icmp --icmp-type 4 -j ACCEPT
# Accept: echo
-A ICMPALL -p icmp -m icmp --icmp-type 8 -j ACCEPT
# Accept: time exceeded
-A ICMPALL -p icmp -m icmp --icmp-type 11 -j ACCEPT
# Drop all other ICMP packets.
-A ICMPALL -p icmp -j DROP

# Reject packet types as appropriate.
-A ZREJ -p tcp -j REJECT --reject-with tcp-reset
-A ZREJ -p udp -j REJECT --reject-with icmp-port-unreachable
-A ZREJ -j REJECT --reject-with icmp-proto-unreachable

Testing the VPN

At this point, you can set up the VPN from a client, with the following settings:

  • Host: 1.2.3.4
  • Type: L2TP/IPsec
    • Pre-shared key (not a certificate): the key defined above
    • Protocol: CHAP (not MS-CHAP v2)
  • Username: a username defined above
  • Password: a password defined above

You should be able to connect successfully, and connect to systems within the internal network at this point. If you are using a Windows system behind a NAT, you may need to set a registry setting and reboot your system prior to being able to connect to the VPN.

Connecting to a Windows domain

The way pppd works on Linux, authenticating against LDAP involves connecting the ppp daemon to RADIUS, then allowing RADIUS to validate credentials against LDAP. Unfortunately, RADIUS performs the validation itself, so it requires authenticating against the VPN server with PAP and storing plaintext passwords within LDAP, which is less than ideal. There is, however, a provision to allow pppd to authenticate against a Windows domain.

First, install winbind:

$ yum install samba-winbind

Set up your /etc/samba/smb.conf with the appropriate information (change the following settings to match those for your own domain):

/etc/samba/smb.conf
[global]
 # Must be all capitals. Adjust to your domain's NetBIOS name.
 workgroup = INTERNAL
 # Adjust to your system's desired NetBIOS name.
 netbios name = VPN
 interfaces = lo eth1
 bind interfaces only = true
 security = ads
 # Must be all capitals. Adjust to your domain's FQDN.
 realm = INTERNAL.LOCAL
 # Set to your domain's PDC.
 password server = pdc.internal.local pdc
  winbind uid = 500-20000
  winbind gid = 500-20000
  winbind enum users = yes
  winbind enum groups = yes
  winbind use default domain = yes

Then, there are several commands to complete the domain setup:

# Restart winbind.
$ service winbind restart
# Join the system to the domain.
$ net ads join -U Administrator
# See whether it's joined.
$ net ads testjoin
# Verify that it's joined by displaying the user list.
$ wbinfo -u

You can clear out the entries from /etc/ppp/chap-secrets, as you won't be using the passwords stored in a text file. Update the following settings in /etc/xl2tpd/xl2tpd.conf:

/etc/xl2tpd/xl2tpd.conf
; Comment out the following line.
; require chap = yes
refuse chap = yes

And the following settings in /etc/ppp/options.xl2tpd:

/etc/ppp/options.xl2tpd
# Replace with your domain controllers.
ms-dns  10.0.0.250

# Add these lines.
require-mschap-v2
require-mppe-128
plugin winbind.so

# Set the following line with the group that controls the list of VPN users.
ntlm_auth-helper '/usr/bin/ntlm_auth --helper-protocol=ntlm-server-1 --require-membership-of="INTERNAL\\VPN Users"'

If you have SELinux enabled, you'll need to generate a policy to allow ntlm_auth to run. You can follow the instructions on this page to figure out how to do so. Your template file should look something like this:

ntlm_auth.te
module winbind_helper 1.0;

require {
       type pppd_t;
       type winbind_helper_exec_t;
        class file { read execute open getattr execute_no_trans };
}

#============= pppd_t ==============
allow pppd_t winbind_helper_exec_t:file execute_no_trans;

#!!!! This avc is allowed in the current policy
allow pppd_t winbind_helper_exec_t:file { read execute open getattr };

The end of the line

Ideally, we would go through and implement user authentication via domain username and password (as above) with machine authentication via certificates. Unfortunately, at least one of the targeted operating systems doesn't support machine certificates for L2TP/IPsec, so there isn't too much value in pursuing it further.