1. Introduction

Hi there 😊. Another day, another post. Today, I thought it would be useful to share some tips and tricks when installing new software on a standalone linux machine / VM.

For cybersecurity researchers that have to adhere to company policy to disconnect research machines from the internet, this post will be useful for your future workflows.

Before I begin the walkthrough, it is important to have 1 internet-connected machine that is of a similar OS Version to the offline machine so as to minimize incompatibilities between systems.

For now, this post will only be going through the steps to install packages offline for Ubuntu and CentOS machines. In the future, I may revist and update this post again if I find more workarounds.

2. Ubuntu

2.1 Editing Apt Source

The first thing you want to do is to edit /etc/apt/sources.list and uncomment the lines that start with deb-src.

Once you are done, your /etc/apt/sources.list should look something like this:

(base) gerald@nexus:~$ cat /etc/apt/sources.list

#deb cdrom:[Ubuntu 22.04.1 LTS _Jammy Jellyfish_ - Release amd64 (20220809.1)]/ jammy main restricted

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://sg.archive.ubuntu.com/ubuntu/ jammy main restricted
deb-src http://sg.archive.ubuntu.com/ubuntu/ jammy main restricted
....
Tip
Depending on the Ubuntu version you are using, the distro name will be different. In my case, my Ubuntu internet-connected machine is 22.04, and hence mine is jammy.

2.2 Downloading Main Package with Dependencies

  1. Make a new directory to save your packages

    user@internet-connected:~$ mkdir $HOME/Downloads/xfer
    
  2. Change directory

    user@internet-connected:~$ cd $HOME/Downloads/xfer
    
  3. Download package with its dependencies

    user@internet-connected:~/Downloads/xfer$ apt-get download \
    $(apt-cache depends --recurse --no-recommends \
    --no-suggests --no-conflicts --no-breaks \
    --no-replaces --no-enhances \
    $PACKAGE_NAME | grep "^\w")
    

2.3 Transfer and Install on Offline Machine

Now that you have the main package with its dependencies, use whichever method you prefer to transfer these packages over to the offline machine.

Then, just run the following command to install all packages. Do not that this is an extremely lazy way of doing things and it does not regard the order in which the packages should be installed.

user@standalone:~/Downloads/xfer$ sudo dpkg -i *.deb

If the above command does not install everything the first time due to the wrong order of dependencies being installed, just run it a few more times until you see that there’s no error. It’s abit stupid…I know. But if it works, it works.

sumikko-gurashi-penguin-throw-book

2.4 ⭐ BONUS - Extracting Libraries and Binaries

Assuming you just want some libraries from the .deb package, you can make use of dpkg-deb extraction.

# SYSROOT_PATH refers to the directory to extract to.
$ dpkg-deb -x $PACKAGE_NAME.deb $SYSROOT_PATH

Here’s also a one liner to extract all .deb packages in the same directory for the lazy people out there like myself.

$ DEBS=($(ls | grep ".deb")); \
for package in "${DEBS[@]}"; \
do dpkg-deb -x $package $SYSROOT_PATH; \
done

3. CentOS

If your CentOS Version has reached EOL (End of Life), you will need to update the remote yum repository URLs. Otherwise, you can skip the steps in sub section 3.1.

3.1 Editing Yum Source

For CentOS Versions that have reached EOL, you may find all archived packages in the following 2 URLs:

  1. https://vault.centos.org/
  2. https://archive.kernel.org/centos-vault/

For this example, I used CentOS 8.5.2111 which has already reached EOL.

For the following 3 repository lists, comment out mirrorlist, and edit the baseurl accordingly:

  1. Edit /etc/yum.repos.d/CentOS-Linux-AppStream.repo:

    ...
    [appstream]
    name=CentOS Linux $releasever - AppStream
    #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
    baseurl=http://archive.kernel.org/centos-vault/8.5.2111/AppStream/$basearch/os/
    ...
    
  2. Edit /etc/yum.repos.d/CentOS-Linux-BaseOS.repo

    ...
    [baseos]
    name=CentOS Linux $releasever - BaseOS
    #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=BaseOS&infra=$infra
    baseurl=http://archive.kernel.org/centos-vault/8.5.2111/BaseOS/$basearch/os/
    ...
    
  3. Edit /etc/yum.repos.d/CentOS-Linux-Extras.repo

    ...
    [extras]
    name=CentOS Linux $releasever - Extras
    #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
    baseurl=http://archive.kernel.org/centos-vault/8.5.2111/extras/$basearch/os/
    ...
    

Once you are done, do a dnf update / yum update to check that the remote reposiotry is working properly.

3.2 Downloading Main Package with Dependencies

You can use either dnf or yum to download your packages.

3.2.1 Using dnf

  1. Install dnf-plugins-core (if not already installed)
    [user@internet-connected ~]$ sudo dnf install dnf-plugins-core
    
  2. Download the package together with its dependencies
    [user@internet-connected ~]$ dnf download --resolve \
    --destdir $HOME/Downloads/xfer \
    $PACKAGE_NAME
    

3.2.2 Using yum

  1. Install yum-utils (if not already installed)
    [user@internet-connected ~]$ sudo yum install yum-utils
    
  2. Download the package together with its dependencies
    [user@internet-connected ~]$ yumdownloader --resolve \
    --destdir $HOME/Downloads/xfer \
    $PACKAGE_NAME
    

3.3 Transfer and Install on Offline Machine

You can use either dnf or yum to install your packages.

3.3.1 Using dnf

[user@standalone ~]$ sudo dnf localinstall *.rpm

3.3.2 Using yum

[user@standalone ~]$ sudo yum localinstall *.rpm

3.4 ⭐ BONUS - Extracting Libraries and Binaries

Assuming you just want some libraries from the .rpm package, you can make use of rpm2cpio and cpio for extraction.

# SYSROOT_PATH refers to the directory to extract to.
[user@localhost ~]$ rpm2cpio $PACKAGE_NAME.rpm \
| (cd $SYSROOT_PATH && cpio -idmv)

Here’s also a one liner to extract all .rpm packages in the same directory for the lazy people out there like myself.

$ RPMS=($(ls | grep ".rpm")); \
for package in "${RPMS[@]}"; \
do rpm2cpio $package \
| (cd $SYSROOT_PATH && cpio -idmv); \
done

4. Conclusion

If you have made it this far, congratulations! sumikko-gurashi

I hope you learnt something useful today and if this works like a charm for you, you are always welcome to come back to reference these set of instructions for your future use. Cheers and have a nice day!