Technology Matters

I recently had a candid conversation with one of our marketing executives, and I was shocked to learn her perspective on IT’s purpose within the company. The conversation was about web site performance. I was talking about how so many of the company’s objectives require IT, including her objectives to improve the web site’s performance. She had been working directly with our internal development team for over a year to get a project rolling to improve our web site’s performance with no traction and no success. Immediately after learning about her objective, I offered a solution. Since our developers were unable to prioritize a project for her, I suggested that we put a layer of caching in front of the site to meet her performance objectives without having our developers modify a single line of code. I explained to her how IT is entrenched in every aspect of the company, charged with the goal of making everyone more efficient and finding creative solutions to the company’s technical challenges. She had no idea that we could help her. She confessed to me that she thought that IT was just the people who sets up her new monitors and replaces her laptops every few years. Very sad.

The saddest thing, is that this marketing executive’s perspective is not an exception, it’s a common belief among other executives as well. By not knowing the role of IT, she excluded us from the conversation and paid for it with a year of lost clicks, lost leads, and lost revenue.

If a company was viewed as Amtrak, then the IT department would be Grand Central Station – the hub in which all paths cross. If a company was viewed as a car, then IT would be the oil and the gas (or batteries). You get the idea. IT is the force that keeps the company productive, on track, online, and competitive. Innovation starts here. If you think IT just sets up your monitors and then goes back to their caves, you are naive and it is very likely that you will struggle to succeed.

Advice – Learn the importance of IT and leverage your IT team to help you succeed! At a minimum, keep them informed. Any modern company without IT representation with a seat at the table, is destined for failure.

Creating a GlusterFS Cluster for VMs

The best GlusterFS layout that I have found to work with VMs is a distributed replicated cluster with shards enabled. I use laptops with 2 drives in each one. Let’s say we have 4 laptops with 2 drives on each one, we would do something like what I have listed below.

First, let’s create a partition on each disk. Use fdisk /dev/sda and fdisk /dev/sdb to create a partition. Now, each disk needs to be formatted as XFS. We format with the command.

mkfs.xfs -i size=512 /dev/sda1
mkfs.xfs -i size=512 /dev/sdb1
mkdir /mnt/disk1
mkdir /mnt/disk2

Now we can use blkid to list the UUID of sda1 and sdb1 so that we can add it to fstab. My fstab looks something like this (your UUIDs will be different. The allocsize is set to pre-allocate files 64MB at a time to limit fragmentation and improve performance. The noatime is to prevent the access time attribute being set every time the file is touched – this is to improve performance as well. The nofail is to prevent the system from not booting in the event of a disk failure.

#!/etc/fstab
UUID=3edc7ec8-303a-42c6-9937-16ef37068c72 /mnt/disk2 xfs defaults,allocsize=64m,noatime,nofail 0 1
UUID=b8906693-27ba-466b-9c39-8066aa765d2e /mnt/disk1 xfs defaults,allocsize=64m,noatime,nofail 0 1

Now I did something funky with my fstab because I wanted to mount my bricks under the volname so that I could have different volumes on the same disks. So I added these lines to my fstab (my volname is “prod”).

#!/etc/fstab
/mnt/disk1/prod/brick1 /mnt/gluster/prod/brick1 none bind 0 0
/mnt/disk2/prod/brick2 /mnt/gluster/prod/brick2 none bind 0 0
mkdir -p /mnt/gluster/prod/brick1
mkdir -p /mnt/gluster/prod/brick2
mount /mnt/disk1 mount /mnt/disk2
mkdir -p /mnt/disk1/prod/brick1
mkdir -p /mnt/disk2/prod/brick2

Now we can mount everything else.

mount -a

Make sure that everything is mounted properly.

df -h /mnt/gluster/prod/brick1

Make sure that you see /dev/sda1 next to it. If not, just reboot and fstab will mount everything appropriately.

Now let’s create the gluster cluster.

gluster volume create prod replica 2 gluster1:/mnt/gluster/prod/brick1 gluster2:/mnt/gluster/prod/brick1 gluster3:/mnt/gluster/prod/brick1 gluster4:/mnt/gluster/prod/brick1 gluster1:/mnt/gluster/prod/brick2 gluster2:/mnt/gluster/prod/brick2 gluster3:/mnt/gluster/prod/brick2 gluster4:/mnt/gluster/prod/brick2

By specifying the order as we did, we ensure that server gluster1 and server gluster2 are paired up with each other, and gluster3 and gluster4 are paired up with each other. If we did both bricks on gluster1 successively, then we would be unable to sustain a failure of the gluster1 node. So we alternate servers. This also improves performance.

Now, the only thing left is to tune some parameters meant for VMs. For each parameter below, we will use a command like the following:

gluster volume set prod storage.fips-mode-rchecksum on

Here are my options:

performance.readdir-ahead: on
performance.client-io-threads: on
nfs.disable: on
transport.address-family: inet
cluster.granular-entry-heal: on
network.ping-timeout: 20
features.shard-block-size: 64MB
client.event-threads: 4
server.event-threads: 4
cluster.data-self-heal-algorithm: full
cluster.shd-max-threads: 8
cluster.shd-wait-qlength: 10000
server.allow-insecure: on
features.shard: on
cluster.server-quorum-type: server
cluster.quorum-type: auto
network.remote-dio: on
cluster.eager-lock: enable
performance.io-cache: off
performance.read-ahead: off
performance.quick-read: off
cluster.locking-scheme: granular
performance.low-prio-threads: 32
cluster.choose-local: off
storage.fips-mode-rchecksum: on
config.transport: tcp

Now we can fire up the gluster cluster with the following command.

gluster volume start prod

Create a UEFI bootable ISO on Debian

First thing’s first… let’s get a quick overview of what’s need, what goes where, and what to expect.

In order to make an ISO bootable, you need an .img file. Many tutorials call this efiboot.img. It’s basically a FAT formatted file that contains a specific folder structure and a specially named executable that UEFI will run. The folder structure should have just one file in it located in /efi/boot/bootx64.efi. The bootx64.efi file is the boot code, so it can be any boot loader that generates it. I like Grub, so that’s what my instructions below do.

Now you may wonder – if you use Grub as the bootx64.efi, then where the heck does it get grub.cfg from? It’s pretty plain and simple – it’s in /boot/grub/grub.cfg just as it would be in a regular filesystem. Except, /boot/grub/grub.cfg lives outside the .img file — it lives along-side it, really.

Ok, now that that’s out of the way, let’s get started. You need some packages first.

sudo apt update
sudo apt install grub-efi-amd64 grub-efi-amd64-bin grub-imageboot grub-legacy grub-pc-bin grub-pc

Now let’s create a rescue image, which will do the heavy lifting for us. Then we will mount it to a temp folder.

grub-mkrescue -o grub.iso
mkdir /tmp/grubcd
mount -o loop grub.iso /tmp/grubcd

Now let’s create the folder where we want our ISO to live. Then we will copy the contents of grub.iso to that folder.

mkdir myiso
cp -avR /tmp/grubcd/* myiso/

Next, let’s create a grub.cfg file so that you can tell it where and what to load. You will want to edit this and not leave it blank.

touch myiso/boot/grub/grub.cfg

Lastly, copy your vmlinuz and initrd files to myiso, along with any other files you need/want. Then you can create your iso with something like xorriso.

cd myiso
xorriso -volid "CDROM" -as mkisofs -isohybrid-mbr isohdpfx.bin -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e grub.img -isohybrid-gpt-basdat -o ../mycd.iso ./

Arch on Chromebook

Apps…

pacman -Sy
pacman -S chromium xorg-server connman enlightenment rxvt-unicode autocutsel; # Note: Choose the noto fonts when prompted
systemctl enable connman

Touchpad support:
/usr/share/X11/xorg.conf.d/70-synaptics.conf

# Example xorg.conf.d snippet that assigns the touchpad driver
# to all touchpads. See xorg.conf.d(5) for more information on
# InputClass.
# DO NOT EDIT THIS FILE, your distribution will likely overwrite
# it when updating. Copy (and rename) this file into
# /etc/X11/xorg.conf.d first.
# Additional options may be added in the form of
#   Option "OptionName" "value"
#
Section "InputClass"
        Identifier "touchpad catchall"
        Driver "synaptics"
        MatchIsTouchpad "on"
# This option is recommend on all Linux systems using evdev, but cannot be
# enabled by default. See the following link for details:
# http://who-t.blogspot.com/2010/11/how-to-ignore-configuration-errors.html
#       MatchDevicePath "/dev/input/event*"
EndSection

Section "InputClass"
        Identifier "touchpad ignore duplicates"
        MatchIsTouchpad "on"
        MatchOS "Linux"
        MatchDevicePath "/dev/input/mouse*"
        Option "Ignore" "on"
EndSection

# This option enables the bottom right corner to be a right button on clickpads
# and the right and middle top areas to be right / middle buttons on clickpads
# with a top button area.
# This option is only interpreted by clickpads.
Section "InputClass"
        Identifier "Default clickpad buttons"
        MatchDriver "synaptics"
        Option "TapButton1" "1"
        Option "TapButton2" "3"
        Option "TapButton3" "2"
        Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
        Option "SecondarySoftButtonAreas" "58% 0 0 15% 42% 58% 0 15%"
EndSection

# This option disables software buttons on Apple touchpads.
# This option is only interpreted by clickpads.
Section "InputClass"
        Identifier "Disable clickpad buttons on Apple touchpads"
        MatchProduct "Apple|bcm5974"
        MatchDriver "synaptics"
        Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
EndSection

xterm / rxvt customizations
~/.Xdefaults

! Perl extension config
URxvt.perl-ext-common: default,selection-to-clipboard
URxvt.perl-ext: tabbed
! Any scripts placed here will override global ones with the same name

!-- Xft settings -- !
!Xft.dpi:        96
!Xft.antialias:  true
!Xft.rgba:       rgb
!Xft.hinting:    true
!Xft.hintstyle:  hintfull

! Tabbed extension configuration
URxvt.tabbed.tabbar-fg: 8
URxvt.tabbed.tabbar-bg: 0
URxvt.tabbed.tab-fg:    15
URxvt.tabbed.tab-bg:    8
URxvt.tabbed.new-button: false

URxvt*depth: 32
URxvt*background: rgba:0000/0000/0200/c800
URxvt*font: xft:NotoSansMono-Medium:size=18:antialias=true
URxvt*foreground:white

/etc/sudoers.d/xorg

%sudo ALL=(ALL)NOPASSWD:/usr/bin/Xorg
%sudo ALL=(ALL)NOPASSWD:/usr/local/bin/Xorg

Uncomment the line in /etc/sudoers to look like this:

%wheel ALL=(ALL) ALL

Add user myuser (change to the name of your user) to wheel.

usermod -aG wheel myuser

Create a file /usr/bin/startx-custom

sudo /usr/bin/Xorg &
sleep 2
export DISPLAY=:0
/usr/bin/autocutsel -fork
if [ `pidof Xorg` ]; then
        /usr/bin/enlightenment_start && killall -s KILL Xorg
else
        echo "No Xorg running... not starting E17"
fi

Make it executable.

chmod a+x /usr/bin/startx-custom

For a high resolution screen like on the Samsung Chromebook Plus, you may want to scale Chromium. To do this, add the following.
~/.config/chromium-flags.conf

--force-device-scale-factor=1.7

If DNS is not working right, adjust /etc/nsswitch.conf to look like this:

hosts: files mymachines myhostname dns resolve [!UNAVAIL=return] dns

Fail-To-Ban (Lite) – EdgeRouter

Here’s how to create a fail-to-ban type of functionality on an EdgeRouter completely using BASH, without installing any 3rd party packages. We are going to create a single script and add a scheduled job to run it. That’s all there is to it.

Step 1
Run the following

vi /config/scripts/fail-to-ban

Now we need to turn off auto indent before copying and pasting the script below. Type the following:

:set noai
i

Now paste the following script into the file:

#!/bin/bash

PATH=$PATH:/usr/bin:/bin:/sbin:/usr/sbin

ATTEMPTS=10;    # NUMBER OF ATTEMPTS IN A GIVEN INTERVAL
INTERVAL=600;   # INTERVAL (IN SECONDS) TO WATCH FOR FAILED ATTEMPTS - HISTORICALLY FROM CURRENT TIME
PERMBAN=100;    # AFTER THIS NUM OF FAILED ATTEMPTS, BAN UNTIL LOG ROTATES
BLOCKSECS=3600; # AFTER THIS TIME (IN SECONDS), UNBLOCK A BLOCKED IP
BLOCKED_ALREADY=""
BLOCKED_NOW=""
SKIPPED=""
EXPIRED_BLOCK=""
NOW=`date '+%s'`

isip() {
  ISIP=$1
  if [ $(echo $IP | sed 's/[^.]//g' | awk '{print length; }' 2> /dev/null) -eq 3 ]; then
    ISIP=1
  fi
}

fail2ban() {
        # echo failing $IP with count $COUNT and lastcount $LASTCOUNT
        IP=$IP
        EXISTS=`nice -19 iptables -n -L | grep $IP | wc -l`
        IS_LOCAL=`echo $IP | grep -E '^10\.|192\.168|127\.' | wc -l`
        if [ $EXISTS -gt 0 ]; then
    BLOCKED_ALREADY+=",$IP:$COUNT"
                # echo "IP $IP is already blocked"
        elif [ $IS_LOCAL -eq 1 ]; then
    SKIPPED+=",$IP:$COUNT"
                # echo "IP is local IP.  Not blocking"
        else
    if [ ! "$IP" == "" ]; then
                  # echo "Blocking IP $IP after $COUNT abuses."
                  BLOCKED_NOW+=",$IP:$COUNT"
                  iptables -I INPUT 1 -j DROP -s $IP
                  echo "`date`:$IP:$NEWCOUNT:$COUNT:BLOCKED" >> /tmp/banned.log
    fi
        fi
}

updateList() {
        NOW=`date '+%s'`
        sed -i /tmp/ip-list.log -e "s/:"$IP":"$LASTCOUNT".*$/:"$IP":"$COUNT":"$NOW"/"
}

updateTime() {
  NOW=`date '+%s'`
  sed -i /tmp/ip-list.log -e "s/:"$IP":"$LASTCOUNT".*$/:"$IP":"$LASTCOUNT":"$NOW"/"
}


showList() {
  LIST="$2"
  DESCRIPTION="$1"
  if [ ! "$LIST" == "" ]; then  
        	echo "$DESCRIPTION"
        	for i in `echo "$LIST"`                                                                       
        	do                                                                                                   
        	        BIP=$(echo $i | sed -e 's/:.*$//')                                                           
        	        BCOUNT=$(echo $i | sed -e 's/^.*://')                                                        
      if [ ! "$BIP" == "" ]; then
                    echo $BIP $BCOUNT                                                                            
      fi
        	done
  fi	
}

checkExpired() {
  BLOCKED=$(nice -19 iptables -L INPUT -n | grep "^DROP" | sed -e 's/^.*--  //' | sed -e 's/ .*$//')
  for i in `grep -e "$BLOCKED" /tmp/ip-list.log`                                                                                                                                              
  do                                                                                                                                                                           
          IP=`echo $i | cut -d':' -f2`                                                                                                                                         
          isip $IP                                                                                                                                                             
          COUNT=`echo $i | cut -d':' -f3`                                                                                                                                      
          LASTACTION=`echo $i | cut -d':' -f4`                                                                                                                                 
                                                                                                                                                                               
          if [ $((NOW-LASTACTION)) -gt $BLOCKSECS ] && [ ! "$IP" == "" ] && [ $ISIP -eq 1 ] && [ $COUNT -lt $PERMBAN ]; then                                                   
                  LINE=`nice -19 iptables -L -n --line-numbers | grep "$IP" | cut -d' ' -f1`                                                                                            
                  if [ ! "$LINE" == "" ]; then                                                                                                                                 
                          echo "Removing block on $IP"                                                                                                                         
        echo "$(date):$IP:UNBLOCKED" >> /tmp/banned.log
                          # EXPIRED_BLOCK+=",$IP"                                                                                                                              
                          echo iptables -D INPUT $LINE                                                                                                                         
                          iptables -D INPUT $LINE                                                                                                                              
                  fi                                                                                                                                                           
          fi                                                                                                                                                                   
  done                                   
}


if [ ! -f /tmp/ip-list.log ]; then
        touch /tmp/ip-list.log
fi

# CLEANUP - KEEP ONLY HACKERS FROM TODAY
echo -n "" > /tmp/ip-list.new
IFS="
"
for i in `grep "^$(date +%Y%m%d):" /tmp/ip-list.log`
do
  if [ ! "$i" == "" ]; then
    echo $i >> /tmp/ip-list.new
  fi
done
mv /tmp/ip-list.new /tmp/ip-list.log

# Do some checking to see if the logs actually changed
if [ -f /tmp/this-run ]; then
  mv /tmp/this-run /tmp/last-run
else
  touch /tmp/last-run
fi
ls -1 --full-time /var/log/auth.log > /tmp/this-run
CHANGE=$(diff /tmp/last-run /tmp/this-run | wc -l)
if [ $CHANGE -eq 0 ]; then
  echo "No change since last run"
  checkExpired
  exit
fi

IPLIST=`nice -19 grep failure /var/log/auth.log | grep rhost | sed -e 's/^.*rhost=//' | sed -e 's/ .*$//' | sort | uniq -c | sed -e 's/^ *//' | sed -e 's/ /:/' | grep -E ":[0-9.]*$" | sed -e "s/^\(.*\)$/$(date +%Y%m%d):\1/"`

for i in `echo "$IPLIST"`
do
  #echo $i
        COUNT=`echo $i | cut -d':' -f2`
        IP=`echo $i | cut -d':' -f3`
  DATE=`echo $i | cut -d':' -f1`
  isip $IP
        LASTCOUNT=`cat /tmp/ip-list.log | grep ":$IP:" | cut -d':' -f3`
        ELAPSED=`cat /tmp/ip-list.log | grep ":$IP:" | cut -d':' -f4 | sed -e 's/\n//g'`
  ELAPSED=$((NOW-ELAPSED))
        if [ "$COUNT" == "" ]; then
                COUNT=0
        fi
        if [ "$LASTCOUNT" == "" ]; then
                LASTCOUNT=0
        fi
        NEWCOUNT=$((COUNT-LASTCOUNT))
        if [ ! "$LASTCOUNT" == "" ] && [ $LASTCOUNT -eq 0 ] && [ $ISIP -eq 1 ]; then
                echo "$DATE:$IP:$COUNT:$NOW" >> /tmp/ip-list.log
               # echo "Adding $IP to the IP tracking log with count $COUNT"
        fi
  # echo "IP:$IP NEWCOUNT:$NEWCOUNT LASTCOUNT:$LASTCOUNT COUNT:$COUNT ELAPSED:$ELAPSED ISIP:$ISIP ATTEMPTS:$ATTEMPTS INTERVAL:$INTERVAL"
  
        if [ $NEWCOUNT -ge $ATTEMPTS ] && [ $ISIP -eq 1 ] && ( [ $ELAPSED -le $INTERVAL ]  ||  [ $COUNT -gt $PERMBAN ] ); then
                if [ $LASTCOUNT -ne 0 ]; then
      echo "Updating IP:$IP with NEWCOUNT:$NEWCOUNT ATTEMPTS:$ATTEMPTS ELAPSED:$ELAPSED INTERVAL:$INTERVAL ISIP:$ISIP"
                        updateList

                fi
                fail2ban
  elif [ $NEWCOUNT -ge $ATTEMPTS ] && [ $ISIP -eq 1 ]; then
    echo "Updating the timestamp for IP $IP; +$NEWCOUNT since last update"
    updateTime
        fi
done

checkExpired

IFS=","

showList "Blocked | Attempts" "$BLOCKED_ALREADY"
showList "Newly Blocked | Attempts" "$BLOCKED_NOW"
showList "Skipped | Attempts" "$SKIPPED"
showList "Expired" "$EXPIRED_BLOCK"

Now you need to exit and save your changes.
esc
:wq

Now let’s make the script executable:

chmod a+x /config/scripts/fail-to-ban

And lastly, we need to add a job to run this periodically and also disable hostname lookups in SSH to make the script’s IP validation work properly and remove a possible DoS vector.

configure
set system task-scheduler task failtoban executable path /config/scripts/fail-to-ban
set system task-scheduler task failtoban interval 1m
set service ssh disable-host-validation
commit
save

Done! Now your EdgeRouter should be protected against brute force login attacks.

Blank Page when signing into Office 365 using Chromium (Fixed)

Symptom: A blank page when accessing https://outlook.office365.com, https://login.microsoftonline.com, or most other Microsoft sites.

Cause: An untrusted root certificate.

Solution: Add the proper Symantec root CA.

  1. Paste in the following into a new file called symantec-ca.cer
  2. -----BEGIN CERTIFICATE-----
    MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB
    yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
    ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
    U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
    ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
    aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw
    CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
    BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs
    YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC
    AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb
    A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW
    9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu
    s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T
    L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK
    Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBYzCCAV8wEgYDVR0T
    AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu
    Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjAvBggrBgEFBQcBAQQjMCEw
    HwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wawYDVR0gBGQwYjBgBgpg
    hkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20v
    Y3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMCkG
    A1UdEQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0xLTUzNDAdBgNVHQ4E
    FgQUX2DPYZBV34RDFIpgKrL1evRDGO8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnz
    Qzn6Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBAF6UVkndji1l9cE2UbYD49qecxny
    H1mrWH5sJgUs+oHXXCMXIiw3k/eG7IXmsKP9H+IyqEVv4dn7ua/ScKAyQmW/hP4W
    Ko8/xabWo5N9Q+l0IZE1KPRj6S7t9/Vcf0uatSDpCr3gRRAMFJSaXaXjS5HoJJtG
    QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t
    TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY
    Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc=
    -----END CERTIFICATE-----

  3. Open Settings->Manage Certificates
  4. Browse to Authorities->Import
  5. Open the symantec-ca.cer file that you saved earlier
  6. That’s it! Now you should be able to access Office 365.

iOS 10 OpenVPN with Active Directory Authentication

With iOS 10, PPTP is out and IPSEC and L2TP are the main options now. PPTP uses a protocol that is neither TCP or UDP – it is GRE. And IPSEC uses yet another protocol called ESP. The problem with most VPNs is that they do not work when you need them to because many hotel and guest networks allow access to only specific protocols, such as TCP/UDP. This tutorial will show you how you can configure a simple OpenVPN server to authenticate your Active Directory users even through environments that are prone to blocking PPTP, IPSEC, and L2TP.

First, let’s download a copy of the very cool open source router, VyOS.
http://packages.vyos.net/iso/release/1.1.7/vyos-1.1.7-amd64.iso

Now, we create a VM with a 2GB partition and we install VyOS. At the prompt, login with vyos/vyos and type:

install image

When asked, set your password of choice for the vyos username. Eject the CD, reboot, and you should get to the login prompt. Login, and let’s get started.

Type the following:

configure
set system package repository squeeze components 'main contrib non-free'
set system package repository squeeze distribution 'squeeze'
set system package repository squeeze url 'http://archive.debian.org/debian'
set system package repository squeeze-lts components 'main contrib non-free'
set system package repository squeeze-lts distribution 'squeeze-lts'
set system package repository squeeze-lts url 'http://archive.debian.org/debian'
sudo apt-get -o Acquire::Check-Valid-Until=false update
sudo apt-get install krb5-config krb5-user libpam-krb5
commit

Now you should have all of the packages that you need, so its time to start configuring kerberos. Type the following:

sudo nano /etc/krb5.conf

Here is a template for a simple krb5.conf file that you will need to modify to match your domain. The IP of your domain controller will be the IP for the kdc. Take note of the case changes for the domain name. Match the example for the case for your domain.

[libdefaults]
        default_realm = MYDOMAIN.LOCAL

[realms]
        MYDOMAIN.LOCAL = {
        kdc = 10.0.0.2
        }

[domain_realms]
        .mydomain.local = MYDOMAIN.LOCAL
        mydomain.local = MYDOMAIN.LOCAL

[appdefaults]
        forwardable = true
        pam = {
            minimum_uid = 1000
            MYDOMAIN.LOCAL = {
                ignore_k5login = true
            }
        }

Now that /etc/krb5.conf is configured, we should be able to do the first test. Let’s run kinit and see if we can login. Here is an example:

kinit myuser

After you type in the password, you should be able to check if you are logged in with the klist command.

klist

If all worked, type the following.

save
exit
reboot now

Now it’s time to configure OpenVPN.
First, let’s copy over the template easy-rsa folder to the config folder so that it persists upon upgrades.

cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /config/easy-rsa2
cd /config/easy-rsa2
source ./vars
./clean-all 
./build-ca
./build-dh
./build-key-server 
./build-key-server  server
cp keys/ca.crt /config/auth/
cp keys/dh1024.pem ../auth/
cp keys/server.key ../auth/
cp keys/server.crt ../auth/
./build-key company

Phew! Ok, now we’re done with the prerequisites to configure OpenVPN. Let’s start configuring VyOS so that it uses all of these new settings.

configure
set interfaces openvpn vtun0 mode server
set interfaces openvpn vtun0 openvpn-option --username-as-common-name
set interfaces openvpn vtun0  openvpn-option "plugin /usr/lib/openvpn/openvpn-auth-pam.so login"
set interfaces openvpn vtun0 persistent-tunnel
set interfaces openvpn vtun0 protocol udp
set interfaces openvpn vtun0 server domain-name mydomain.local
set interfaces openvpn vtun0 server subnet 10.0.1.0/24
set interfaces openvpn vtun0 server name-server 10.0.0.2
set interfaces openvpn vtun0 push-route 10.0.0.0/16
set interfaces openvpn vtun0 tls ca-cert-file /config/auth/ca.crt
set interfaces openvpn vtun0 tls cert-file /config/auth/server.crt
set interfaces openvpn vtun0 tls dh-file /config/auth/dh1024.pem
set interfaces openvpn vtun0 tls key-file /config/auth/server.key
commit
exit

We are almost there. Now we just need to create the .ovpn file. Replace the sections between , , and with the contents of the files /config/auth/ca.crt, /config/auth/company.crt, and /config/auth/company.key. Hint: You can get the contents by typing something like: cat /config/auth/ca.crt.

client
remote VPN.mydomain.com 1194
proto udp
dev tun
resolv-retry infinite
nobind
persist-key
persist-tun

-----BEGIN CERTIFICATE-----
........................................
........................................
........................................
........................................
.........................==
-----END CERTIFICATE-----


-----BEGIN CERTIFICATE-----
........................................
........................................
........................................
........................................
.........................==
-----END CERTIFICATE-----


-----BEGIN RSA PRIVATE KEY-----
........................................
........................................
........................................
........................................
.........................==
-----END RSA PRIVATE KEY-----

auth-user-pass

Install OpenVPN Connect on your iOS 10 device.
Copy your .ovpn file onto your device and open it.
Enter your username/pass and you’re ready to go.

Note: It is not imperative that each person has a unique certificate because they need to authenticate their user/pass in order to connect (and we use their username to register instead of their certificate name). If you are not happy with the security risk of re-using certificates, you can generate a new certificate for each person by using the ./build-key script in the /config/easy-rsa2 folder.

The Fastest and Easiest Way to Clone a PC on a Network

This is a guide for using the automated clone assistant on RestartOS to clone a PC over a network. We have a source PC and a target PC. The source PC has the content that we want, and the target PC’s disk will be overwritten with the data from the source PC’s disk. In this guide both PCs have a single disk drive to keep the instructions simple. If you have more than one disk, you can repeat the steps for each disk.

Target PC

First, we launch the software on the target PC.
clone-target-launch

Then we choose the disk that we want to overwrite and confirm our selection.
clone-target-step1

Source PC

Next, we launch the software on the source PC.
clone-source-launch

We choose the disk that we want to clone and then we wait for the system to find the target PC automatically.
clone-source-step1

We confirm the IP address of the target PC (as is seen in step #2 above) and just press enter (or type “y”) to proceed.
clone-source-step2

That’s it! The cloning starts. No IPs to type in. No hassle of copying over MBRs. And it’s very fast.. like 15 minutes for a Windows 10 install fast.
success

How To Change a Xenserver VM Type

Here is a quick and dirty script to change the VM type of an existing Xenserver VM. This can be useful if you are, let’s say, using Linux-based cloning software to clone a Windows VM and you want it to run as fast as possible. You may realize that the system runs very slow. That’s because the Windows VM handles paravirtualization differently than the Linux environment will. You have to change the device type, and this script will help. I added a layer of abstraction to simplify the whole process of switching VM types.

Here are examples of how to run the script:
./change-type myvm This will print out the current VM type as either “windows” or “linux”. A numerical ID is printed in [] that designates the current device_id, for your information.
change-type myvm linux This will change the device type from whatever it is now, to linux.
change-type myvm windows This will change the device type from whatever it is now, to windows.
change-type 00000000-0000-0000-0000-000000000000 linux This will change the device type for the machine with the UUID specified.

#!/bin/bash
# /usr/bin/change-type
#
# Written by Pete Lombardo
#
# This script can change the type of hardware for a VM in a Xen Pool(for example, from Linux to Windows or visa versa).
# It can also be used to resolve a blue screen issue after upgrading the tools inside a Windows VM.
#

if [ ! "$1" == "" ]; then
        uuidtest=`echo $1 | sed -e 's/\-//g' | egrep "[0-9a-f]{32}" | wc -l`
        if [ $uuidtest -eq 0 ]; then
                uuid=`xe vm-list | grep -i ": $1" -B1 | grep uuid | cut -d':' -f2 | cut -d' ' -f2`
                name="$1"
        else
                uuid=$1
                name=`xe vm-list | grep "$uuid" -A1 | grep name | cut -d':' -f2 | cut -d' ' -f2-`
        fi
fi

if [ "$1" == "" ]; then
        echo
        echo "Usage: change-type [machine-name] [type]"
        echo "Available Types: linux,windows"
        echo
        exit
elif [ "$2" == "" ]; then
        echo
        echo "Checking the device type for $name"
        if [ "$uuid" == "" ]; then
                echo
                echo "ERROR: System $1 not found."
                echo
                exit
        fi
        type=`xe vm-param-get uuid=$uuid param-name=platform param-key=device_id 2>/dev/null`
        case $type in
                0001)
                        echo "linux [$type]"
                        ;;
                0002)
                        echo "windows [$type]"
                        ;;
                *)
                        echo "linux [$type]"
                        ;;
        esac
        echo
        exit
fi

case $2 in
linux)
        device="0001"
        ;;
windows)
        device="0002"
        ;;
esac

if [ "$uuid" == "" ]; then
        echo
        echo "ERROR: System $1 not found."
        echo
        exit
fi

xe vm-param-set uuid=$uuid platform:device_id=$device

echo
type=`xe vm-param-get uuid=$uuid param-name=platform param-key=device_id`
        case $type in
                0001)
                        echo "linux [$type]"
                        ;;
                0002)
                        echo "windows [$type]"
                        ;;
                *)
                        echo "linux [$type]"
                        ;;
        esac
echo