Created
October 4, 2017 09:20
-
-
Save fumiyas/b4aaee83e113e061d1ee8ab95b35608b to your computer and use it in GitHub Desktop.
Build OpenSSH with static linked zlib and OpenSSL libraries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -u | |
set -e | |
umask 0077 | |
prefix="/opt/openssh" | |
top="$(pwd)" | |
root="$top/root" | |
build="$top/build" | |
export CPPFLAGS="-I$root/include -L." | |
rm -rf "$root" "$build" | |
mkdir -p "$root" "$build" | |
gzip -dc dist/zlib-*.tar.gz |(cd "$build" && tar xf -) | |
cd "$build"/zlib-* | |
./configure --prefix="$root" --static | |
make | |
make install | |
cd "$top" | |
gzip -dc dist/openssl-*.tar.gz |(cd "$build" && tar xf -) | |
cd "$build"/openssl-* | |
./config --prefix="$root" no-shared | |
make | |
make install | |
cd "$top" | |
gzip -dc dist/openssh-*.tar.gz |(cd "$build" && tar xf -) | |
cd "$build"/openssh-* | |
cp -p "$root"/lib/*.a . | |
[ -f sshd_config.orig ] || cp -p sshd_config sshd_config.orig | |
sed \ | |
-e 's/^#\(PubkeyAuthentication\) .*/\1 yes/' \ | |
-e '/^# *Kerberos/d' \ | |
-e '/^# *GSSAPI/d' \ | |
-e 's/^#\([A-Za-z]*Authentication\) .*/\1 no/' \ | |
sshd_config.orig \ | |
>sshd_config \ | |
; | |
./configure --prefix="$prefix" --with-privsep-user=nobody --with-privsep-path="$prefix/var/empty" | |
make | |
#make install | |
cd "$top" |
I also fix some issues with original script. My version:
#!/usr/bin/env bash
set -uex
umask 0077
ZLIB_VERSION=1.2.11
OPENSSL_VERSION=1.1.1k
OPENSSH_VERSION=V_8_5_P1
prefix="/opt/openssh"
top="$(pwd)"
root="$top/root"
build="$top/build"
dist="$top/dist"
export CPPFLAGS="-I$root/include -L. -fPIC"
export CFLAGS="-I$root/include -L. -fPIC"
export LDFLAGS="-L$root/lib"
rm -rf "$root" "$build" "$dist"
mkdir -p "$root" "$build" "$dist"
curl --output $dist/zlib-$ZLIB_VERSION.tar.gz --location https://zlib.net/zlib-$ZLIB_VERSION.tar.gz
gzip -dc $dist/zlib-*.tar.gz |(cd "$build" && tar xf -)
cd "$build"/zlib-*
./configure --prefix="$root" --static
make
make install
cd "$top"
curl --output $dist/openssl-$OPENSSL_VERSION.tar.gz --location https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz
gzip -dc $dist/openssl-*.tar.gz |(cd "$build" && tar xf -)
cd "$build"/openssl-*
./config --prefix="$root" no-shared
make
make install
cd "$top"
curl --output $dist/openssh-$OPENSSH_VERSION.tar.gz --location https://github.com/openssh/openssh-portable/archive/refs/tags/$OPENSSH_VERSION.tar.gz
gzip -dc $dist/openssh-*.tar.gz |(cd "$build" && tar xf -)
cd "$build"/openssh-*
cp -p "$root"/lib/*.a .
[ -f sshd_config.orig ] || cp -p sshd_config sshd_config.orig
sed \
-e 's/^#\(PubkeyAuthentication\) .*/\1 yes/' \
-e '/^# *Kerberos/d' \
-e '/^# *GSSAPI/d' \
-e 's/^#\([A-Za-z]*Authentication\) .*/\1 no/' \
sshd_config.orig \
>sshd_config \
;
autoreconf
./configure --enable-static LIBS="-lpthread" --prefix="$root" --with-privsep-user=nobody --with-privsep-path="$prefix/var/empty"
make
#make install
cd "$top"
After:
ldd sshd
linux-vdso.so.1 (0x00007fff1e0a8000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f624e0c9000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f624e0c4000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f624e0a1000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f624e066000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f624de74000)
/lib64/ld-linux-x86-64.so.2 (0x00007f624e4d0000)
configure: WARNING: unrecognized options: --enable-static
Install build dependencies
apt update && apt install -y curl gcc make autoconf
Binaries produced
0755:ssh
0755:scp
0755:ssh-add
0755:ssh-agent
0755:ssh-keygen
0755:ssh-keyscan
0755:sshd
4711:ssh-keysign
0755:ssh-pkcs11-helper
0755:ssh-sk-helper
0755:sftp
0755:sftp-server
Oneliner list:
ssh scp ssh-add ssh-agent ssh-keygen ssh-keyscan sshd ssh-keysign ssh-pkcs11-helper ssh-sk-helper sftp sftp-server
Updated to latest libraries (up to OpenSSH 9.6p1), modified for building openssh, added some if for debugging
#!/usr/bin/env bash
set -uex
umask 0077
ZLIB_VERSION=1.3
OPENSSL_VERSION=3.2.0
OPENSSH_VERSION=V_9_6_P1
prefix="/opt/openssh"
top="$(pwd)"
root="$top/root"
build="$top/build"
dist="$top/dist"
export "CPPFLAGS=-I$root/include -L. -fPIC"
export "CFLAGS=-I$root/include -L. -fPIC"
export "LDFLAGS=-L$root/lib -L$root/lib64"
#COMMENT THIS for debugging the script. Each stage will cache download and build
#rm -rf "$root" "$build" "$dist"
mkdir -p "$root" "$build" "$dist"
if [ ! -f "build/zlib-$ZLIB_VERSION/minigzip" ]; then
echo "---- Building ZLIB -----"
if [ ! -f "$dist/zlib-$ZLIB_VERSION.tar.gz" ]; then
curl --output $dist/zlib-$ZLIB_VERSION.tar.gz --location https://zlib.net/zlib-$ZLIB_VERSION.tar.gz
gzip -dc $dist/zlib-*.tar.gz |(cd "$build" && tar xf -)
fi
cd "$build"/zlib-*
./configure --prefix="$root" --static
make
make install
cd "$top"
fi
if [ ! -f "build/openssl-$OPENSSL_VERSION/wow" ]; then
echo "---- Building OpenSSL -----"
if [ ! -f "$dist/openssl-$OPENSSL_VERSION.tar.gz" ]; then
curl --output $dist/openssl-$OPENSSL_VERSION.tar.gz --location https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz
gzip -dc $dist/openssl-*.tar.gz |(cd "$build" && tar xf -)
fi
cd "$build"/openssl-*
./config --prefix="$root" no-shared no-tests
make
make install
cd "$top"
fi
if [ ! -f "$dist/openssh-$OPENSSH_VERSION.tar.gz" ]; then
curl --output $dist/openssh-$OPENSSH_VERSION.tar.gz --location https://github.com/openssh/openssh-portable/archive/refs/tags/$OPENSSH_VERSION.tar.gz
fi
gzip -dc $dist/openssh-*.tar.gz |(cd "$build" && tar xf -)
cd "$build"/openssh-*
cp -p "$root"/lib/*.a .
[ -f sshd_config.orig ] || cp -p sshd_config sshd_config.orig
sed \
-e 's/^#\(PubkeyAuthentication\) .*/\1 yes/' \
-e '/^# *Kerberos/d' \
-e '/^# *GSSAPI/d' \
-e 's/^#\([A-Za-z]*Authentication\) .*/\1 no/' \
sshd_config.orig \
>sshd_config \
;
export PATH=$root/bin:$PATH
autoreconf
./configure LIBS="-lpthread" "--prefix=$root" "--exec-prefix=$root" --with-privsep-user=nobody --with-privsep-path="$prefix/var/empty" "--with-ssl-dir=$root"
make
cd "$top"
And my sloppy patch for CentOS 6.
It'd be nice to know what's wrong there (old autoconf?).
#!/usr/bin/env bash
set -uex
umask 0077
ZLIB_VERSION=1.3
OPENSSL_VERSION=1.1.1w
OPENSSH_VERSION=V_9_6_P1
prefix="/opt/openssh"
top="$(pwd)"
root="$top/root"
build="$top/build"
dist="$top/dist"
export "CPPFLAGS=-I$root/include -L. -fPIC"
export "CFLAGS=-I$root/include -L. -fPIC"
export "LDFLAGS=-L$root/lib -L$root/lib64"
#COMMENT THIS for debugging the script. Each stage will cache download and build
#rm -rf "$root" "$build" "$dist"
mkdir -p "$root" "$build" "$dist"
if [ ! -f "build/zlib-$ZLIB_VERSION/minigzip" ]; then
echo "---- Building ZLIB -----"
if [ ! -f "$dist/zlib-$ZLIB_VERSION.tar.gz" ]; then
curl --output $dist/zlib-$ZLIB_VERSION.tar.gz --location https://zlib.net/zlib-$ZLIB_VERSION.tar.gz
gzip -dc $dist/zlib-*.tar.gz |(cd "$build" && tar xf -)
fi
cd "$build"/zlib-*
./configure --prefix="$root" --static
make
make install
cd "$top"
fi
if [ ! -f "build/openssl-$OPENSSL_VERSION/wow" ]; then
echo "---- Building OpenSSL -----"
if [ ! -f "$dist/openssl-$OPENSSL_VERSION.tar.gz" ]; then
curl --output $dist/openssl-$OPENSSL_VERSION.tar.gz --location https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz
gzip -dc $dist/openssl-*.tar.gz |(cd "$build" && tar xf -)
fi
cd "$build"/openssl-*
./config --prefix="$root" no-shared no-tests
make
make install
cd "$top"
fi
if [ ! -f "$dist/openssh-$OPENSSH_VERSION.tar.gz" ]; then
curl --output $dist/openssh-$OPENSSH_VERSION.tar.gz --location https://github.com/openssh/openssh-portable/archive/refs/tags/$OPENSSH_VERSION.tar.gz
fi
gzip -dc $dist/openssh-*.tar.gz |(cd "$build" && tar xf -)
cd "$build"/openssh-*
cp -p "$root"/lib/*.a .
DISTRO_REL=`cat /etc/*release | tail -n1`
case "$DISTRO_REL" in
CentOS\ release\ 6*) sed -i '/.*OSSH_CHECK_CFLAG_COMPILE[(].*/d' ./configure.ac;
sed -i '/.*OSSH_CHECK_LDFLAG_LINK[(].*/d' ./configure.ac;
sed -i '/.*OSSH_CHECK_CFLAG_LINK[(].*/d' ./configure.ac;
sed -i '/.*OSSH_CHECK_HEADER_FOR_FIELD[(].*/d' ./configure.ac;
sed -i 's/[[] []]/\[\"\"\]/g' ./configure.ac;
;;
*) ;;
esac
[ -f sshd_config.orig ] || cp -p sshd_config sshd_config.orig
sed \
-e 's/^#\(PubkeyAuthentication\) .*/\1 yes/' \
-e '/^# *Kerberos/d' \
-e '/^# *GSSAPI/d' \
-e 's/^#\([A-Za-z]*Authentication\) .*/\1 no/' \
sshd_config.orig \
>sshd_config \
;
export PATH=$root/bin:$PATH
autoreconf
./configure LIBS="-pthread" "--prefix=$root" "--exec-prefix=$root" --with-privsep-user=nobody --with-privsep-path="$prefix/var/empty" "--with-ssl-dir=$root"
make
cd "$top"
为啥openssh没有make install
Improved version:
- Build OpenSSH really static this time
- Lot's of checks
- Some bugfixes
- Remove unnecessary code (including messing with sshd_config)
- Less assumptions
- Readable code
- Build() function to skip things that happen multiple times
- Comments to clarify what happens
- Versions updated
- Warn before running
#!/usr/bin/env sh
ZLIB_VERSION=1.3.1
OPENSSL_VERSION=3.2.0
OPENSSH_VERSION=V_9_6_P1
prefix="/opt/openssh" # Installation directory of OpenSSH
top="$(pwd)" # Directory where we will download and compile everything (current directory)
root="$top/root" # Subdirectory where we will install everything.
build="$top/build" # Subdirectory where we will compile everything.
dist="$top/dist" # Subdirectory where we will download everything.
ZLIB_DIR="zlib-${ZLIB_VERSION}"
ZLIB_TGZ="$ZLIB_DIR.tar.gz"
ZLIB_URL="https://zlib.net/${ZLIB_TGZ}"
ZLIB_CHECKFILE="lib/libz.a"
#Make sure it ends up in $root/lib(64), --static is needed because zlib doesn't like that you build static if you don't mention it before
ZLIB_BUILD_COMMANDS="./configure --prefix=\"$root\" --static && make && make install"
OPENSSL_DIR="openssl-${OPENSSL_VERSION}"
OPENSSL_TGZ="$OPENSSL_DIR.tar.gz"
OPENSSL_URL="https://www.openssl.org/source/${OPENSSL_TGZ}"
OPENSSL_CHECKFILE="bin/openssl"
OPENSSL_BUILD_COMMANDS="./config --prefix=\"$root\" no-tests && make && make install" #Make sure it ends up in $root/lib(64) and don't waste time with tests
OPENSSH_DIR="openssh-portable-${OPENSSH_VERSION}"
OPENSSH_TGZ="$OPENSSH_DIR.tar.gz"
OPENSSH_URL="https://github.com/openssh/openssh-portable/archive/refs/tags/${OPENSSH_VERSION}.tar.gz"
OPENSSH_CHECKFILE="bin/ssh"
#Make sure it ends up in $root/bin, that it drops privileges and that it should use the OpenSSL instead of the one that comes with the ssh source code
OPENSSH_BUILD_COMMANDS="autoreconf && ./configure --prefix=\"$root\" --exec-prefix=\"$root\" --with-privsep-user=nobody --with-ssl-dir=\"$root\" && make && make install"
read -p "We will be working in $top, things might get messy (t)here. Press Ctrl+C to cancel now or Enter to continue" ignorethisvariable
set -uex # Show each command before executing it and exits when a command returns a non-zero exit code or a variable is used without being set
umask 0077 # Make sure that no one except the owner can read, write, or execute newly created files
export "CPPFLAGS=-I$root/include -L. -fPIC -pthread"; export "CFLAGS=$CPPFLAGS" # Compiler will look for headers in $root/include, libraries in the current directory and generate position-independent code and use pthreads
export "LDFLAGS=-L$root/lib -L$root/lib64 -static" # Linker will look for libraries in $root/lib and $root/lib64 and link statically
#Check if everything needed is available
autoreconf --version || { echo "You still need to install autoconf"; exit 1; }
aclocal --version || { echo "You still need to install automake"; exit 1; }
curl --version || { echo "You still need to install curl"; exit 1; }
perl -v || { echo "You still need to install perl"; exit 1; } # OpenSSL's ./configure needs perl
make --version || { echo "You still need to install make"; exit 1; }
gcc --version || { echo "You still need to install gcc"; exit 1; }
[ -f /usr/include/linux/mman.h ] || { echo "You don't have the Linux kernel headers installed"; exit 1; }
echo "#include <stdio.h>" | gcc -E - -o /dev/null || { echo "You still need to install the C library development files"; exit 1; }
mkdir -p "$root" "$build" "$dist" # Create directories if they don't exist
build() {
local name="$1"; local version="$2"; local dir="$3"; local tgz="$4"; local url="$5"; local checkfile="$6"; local buildcommands="$7"
if [ ! -f "$root/$checkfile" ]; then # Only skip this stage if we have already have a correctly $name $version
echo "---- Building $name $version -----"
rm -rf "$build/$dir" # Remove garbage from previous failed builds
if [ ! -f "$dist/$tgz" ]; then # If we didn't download the source code yet
curl --output $dist/$tgz --location $url # Download the source code
fi
tar -C $build -xzf $dist/$tgz || { echo "Extracting $dist/$tgz failed, probably because the download failed"; exit 1; } # Extract the source code
cd "$build"/$dir
eval $buildcommands || { echo "Building $name $version failed"; exit 1; }
else
echo "---- We already have $name $version -----"
fi
cd "$top"
}
build "ZLIB" "$ZLIB_VERSION" "$ZLIB_DIR" "$ZLIB_TGZ" "$ZLIB_URL" "$ZLIB_CHECKFILE" "$ZLIB_BUILD_COMMANDS"
build "OpenSSL" "$OPENSSL_VERSION" "$OPENSSL_DIR" "$OPENSSL_TGZ" "$OPENSSL_URL" "$OPENSSL_CHECKFILE" "$OPENSSL_BUILD_COMMANDS"
build "OpenSSH" "$OPENSSH_VERSION" "$OPENSSH_DIR" "$OPENSSH_TGZ" "$OPENSSH_URL" "$OPENSSH_CHECKFILE" "$OPENSSH_BUILD_COMMANDS"
echo "Everything done. You can find the statically linked OpenSSH binaries in $root/bin"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
should also add
export CFLAGS="-I$root/include -L. -fPIC"
and add-fPIC
to CPPFLAGS and change--prefix="$root"
in line 43. Thank you for sharing.