Skip navigation

Duo Unix - Two-Factor Authentication for SSH (login_duo)

Last Updated: April 19th, 2021

Duo can be easily added to any Unix system to protect remote (SSH) logins with the addition of a simple login_duo module. It has been tested on Linux (RedHat, Fedora, CentOS, Debian, Ubuntu, Amazon Linux), BSD (FreeBSD, NetBSD, OpenBSD), Solaris, and AIX. The code is open-source and available on GitHub.

Duo Network Gateway provides SSH access to internal hosts without a VPN or jump host with trusted endpoint detection and session awareness. Learn more.


Duo can be enabled on any Unix system with the addition of a simple login_duo utility. We recommend deploying our pam_duo module with Pluggable Authentication Modules (PAM) support instead of login_duo in most scenarios for the most secure and customizable experience, especially if port forwarding and tunneling is used in your environment.

Connectivity Requirements

This application communicates with Duo's service on TCP port 443. Firewall configurations that restrict outbound access to Duo's service with rules using destination IP addresses or IP address ranges aren't recommended, since these may change over time to maintain our service's high availability. If your organization requires IP-based rules, please review this Duo KB article.

Walkthrough Video

First Steps

Before moving on to the deployment steps, it's a good idea to familiarize yourself with Duo administration concepts and features like options for applications, available methods for enrolling Duo users, and Duo policy settings and how to apply them. See all Duo Administrator documentation.

Then you'll need to:

  1. Sign up for a Duo account.
  2. Log in to the Duo Admin Panel and navigate to Applications.
  3. Click Protect an Application and locate UNIX Application in the applications list. Click Protect to get your integration key, secret key, and API hostname. You'll need this information to complete your setup. See Protecting Applications for more information about protecting applications in Duo and additional application options.
  4. Download the latest version of duo_unix (view checksum). From the command line you can use curl or wget to download the file, like $ wget
Treat your secret key like a password

The security of your Duo application is tied to the security of your secret key (skey). Secure it as you would any sensitive credential. Don't share it with unauthorized individuals or email it to anyone under any circumstances!


FIPS Support

Duo Unix is FIPS-compliant as of version 1.10.4 when run on any machine that has an operating system-wide FIPS mode (like Centos/RedHat 7, Ubuntu 16.04, etc.). No additional flags or options are required.

Install login_duo Prerequisites

OpenSSL development headers and libraries are required for login_duo. When compiling on SUSE/SLES, the zlib package is also necessary.

Dependency Platform Installation
OpenSSL FreeBSD, NetBSD Installed by default
Debian, Ubuntu apt-get install libssl-dev
Red Hat, Fedora, CentOS, Amazon Linux yum install openssl-devel
SUSE/SLES zypper install libopenssl-devel
Solaris pkg install openssl
AIX 3rd party packages or source build
zlib SUSE/SLES zypper install zlib-devel

You also need a compiler like gcc installed on your system to build Duo Unix.

Install login_duo

Once the required dependencies are built and installed, build and install duo_unix.

  1. Extract the downloaded tarball for duo_unix and change to the extracted directory (note your actual extracted directory name reflects the actual version downloaded; the example syntax below references version 1.11.4). View checksums for Duo downloads here.

    $ tar zxf duo_unix-latest.tar.gz
    $ cd duo_unix-1.11.4
  2. Build and install duo_unix.

    $ ./configure --prefix=/usr && make && sudo make install

    For advanced build options, see the README file in the source tarball.

  3. Once duo_unix is installed, edit login_duo.conf (in /etc/duo or /etc/security) to add the integration key, secret key, and API hostname from your Duo Unix application.

    ; Duo integration key
    ; Duo secret key
    skey = SECRET_KEY
    ; Duo API hostname
    host = API_HOSTNAME
  4. You may also add optional Duo configuration options to login_duo.conf. See the table in Duo Configuration Options for all available settings.

Test login_duo

As a regular user, test login_duo manually by running

$ /usr/sbin/login_duo

On some systems, you may instead have to run /usr/local/sbin/login_duo.

If everything is set up correctly, you'll be given an enrollment link and prompted to enroll:

Visit the URL, enroll your phone, and then try login_duo again, this time adding a command to run after authentication is complete:

$ /usr/sbin/login_duo echo 'YOU ROCK!'

You should see something like this:

If you are having trouble with these steps, or if you aren't getting a Duo login prompt, try running login_duo with the -d flag to enable debug output.

Enable login_duo

To protect remote access via SSH, use login_duo.

To enable two-factor authentication for any SSH login method (password, pubkey, etc.) for any user, edit your sshd_config (usually in /etc or /etc/ssh) to add the following line:

This feature is only available with OpenSSH 4.4+.

ForceCommand /usr/sbin/login_duo

This ForceCommand directive instructs sshd to run login_duo (to perform two-factor authentication) before any other requested commands. However, according to the sshd documentation: "The command is invoked by using the user's login shell with the -c option." This means that shell rc files (e.g. .bashrc, .cshrc, etc.) execute before login_duo; if users can edit these files, they may be able to disable Duo authentication for their own accounts. Keep in mind that ForceCommand also disables command=. Mitigate these issues by deploying pam_duo instead of login_duo.

We strongly recommend that you disable PermitTunnel and AllowTcpForwarding in your sshd_config when using login_duo to protect SSH logins. Since OpenSSH sets up port forwarding and tunneling before Duo's two-factor challenge, an attacker may be able to access internal services via port forwarding before completing secondary authentication. Adding the following lines to your sshd_config will prevent this scenario:

PermitTunnel no
AllowTcpForwarding no

You can also optionally limit two-factor authentication to a subset of users whose primary or supplementary group is specified in login_duo.conf. For example:

group = wheel

If you'd like to enable Duo only for specific accounts using SSH pubkeys, use the command option in those users' authorized_keys instead. For example, to verify each admin authorized to log into a shared root account, your ~/.ssh/authorized_keys might look something like this:

command="/usr/sbin/login_duo -f user1" ssh-dss FRP...FD== user1@company
command="/usr/sbin/login_duo -f user2" ssh-dss YUX...IO== user2@company

Now restart the SSH service.

This also works for user-local installations (e.g. in $HOME/bin) without root access — just specify the location of login_duo.conf with the -c flag.

Linux Distribution Packages

To more easily install and maintain Duo Unix deployments, we've built Linux packages for a variety of popular distributions. These packages are tested against the specific listed versions of their respective distributions. Please test all packages thoroughly prior to deploying them into your environment to ensure a great experience.

To download the packages, you'll need Duo's GPG key. The GPG key verifies the Duo Unix package for currently supported OS distributions and versions.

We updated the Duo GPG key for packages on supported distros on May 18, 2020. If you installed Duo before May 2020, use these commands to update the GPG key before the next time you install or upgrade Duo Unix.

The current Duo GPG key expires in May 2030.

CentOS and Red Hat Enterprise Linux (RHEL)

rpm --import

Ubuntu and Debian

curl -s | sudo apt-key add -

OS distributions identified as no longer supported in the distro-specific packages sections use a previous GPG key. We won't replace or update the GPG key on these EOL versions when it expires, and urge you to update to a supported OS.


Tested against 8.0 64-bit, 7.1 64-bit, 6.7 32/64-bit, and 5.11 32/64-bit

IMPORTANT: Duo Unix 1.11.0 is the last release with CentOS 5 support.

Create /etc/yum.repos.d/duosecurity.repo with the following contents:

name=Duo Security Repository

Execute the following shell commands for Centos 6 and later:

# rpm --import
# yum install duo_unix

Execute the following shell commands for Centos 5:

This GPG key expires in August 2020.

# rpm --import
# yum install duo_unix


Tested against 20.04 focal 64-bit, 18.04 bionic 64-bit, 16.04 xenial 32/64-bit, 14.04.3 trusty 32/64-bit, and 12.04.5 precise 32/64-bit.

IMPORTANT: Duo Unix 1.11.3 is the last release with Ubuntu 12.04 support.

Create /etc/apt/sources.list.d/duosecurity.list with the following contents:

deb precise main


deb trusty main


deb xenial main


deb [arch=amd64] bionic main


deb [arch=amd64] focal main

Execute the following shell commands for Ubuntu 14.04 and later:

# curl -s | sudo apt-key add -
# apt-get update && apt-get install duo-unix

Execute the following shell commands for Ubuntu 12.04:

This GPG key expires in October 2024.

# curl -s | sudo apt-key add -
# apt-get update && apt-get install duo-unix

Red Hat Enterprise Linux

Tested against 8.0 64-bit, 7.0 64-bit, 6.4 32/64-bit, and 5.10 32/64-bit.

IMPORTANT: Duo Unix 1.11.0 is the last release with RHEL 5 support.

Create /etc/yum.repos.d/duosecurity.repo with the following contents:

name=Duo Security Repository

Execute the following shell commands for Red Hat 6 and later:

# rpm --import
# yum install duo_unix

Execute the following shell commands for Red Hat 5:

This GPG key expires in August 2020.

# rpm --import
# yum install duo_unix


Tested against 10.0 32/64-bit, 7.9 32/64-bit, 9.5 32/64-bit, 8.2 32/64-bit, and 6.0.10 32/64-bit.

IMPORTANT: Duo Unix 1.11.1 is the last release with Debian 7 support and 1.9.19 is the last release with Debian 6 support.

Create /etc/apt/sources.list.d/duosecurity.list with the following contents:

deb https// squeeze main


deb wheezy main


deb jessie main


deb stretch main


deb buster main

Execute the following shell commands for Debian 8 and later:

# curl -s | sudo apt-key add -
# apt-get update && apt-get install duo-unix

Execute the following shell commands for Debian 6 or 7:

This GPG key expires in August 2020.

# curl -s | sudo apt-key add -
# apt-get update && apt-get install duo-unix


Need some help? Take a look at the Duo UNIX Frequently Asked Questions (FAQ) page or try searching our Duo UNIX Knowledge Base articles or Community discussions. For further assistance, contact Support.

If you open a support case with Duo, be sure to use the Duo Unix Support Tool to create a tarball you can send to the support engineer to aid with troubleshooting.

Duo Configuration Options

The login_duo.conf configuration files use the INI format. It can take the following options:

Key Required? Description
ikey Required Your integration key
skey Required Your secret key
host Required Your API hostname i.e.
groups Optional

If specified, Duo authentication is required only for users whose primary group or supplementary group list matches one of the space-separated pattern lists.

A pattern consists of zero or more non-whitespace characters, "*" (a wild card that matches zero or more characters), or "?" (a wildcard that matches exactly one character).

A pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark ("!"). For example, to specify Duo authentication for all users (except those that are also admins), and for guests:

groups=users,!wheel,!*admin guests

failmode Optional

On service or configuration errors that prevent Duo authentication, fail "safe" (allow access) or "secure" (deny access). The default is "safe".

pushinfo Optional

Include information such as the command to be executed in the Duo Push message. Either "yes" or "no". The default is "no".

http_proxy Optional

Use the specified HTTP proxy, same format as the HTTP_PROXY environment variable. (honored by wget, curl, etc.).

autopush Optional

Either "yes" or "no". Default is "no". If "yes", Duo Unix will automatically send a push login request to the user's phone, falling back on a phone call if push is unavailable. Note that this effectively disables passcode authentication. If "no", the user will be prompted to choose an authentication method.

When configured with autopush = yes, we recommend setting prompts = 1.

motd Optional

Print the contents of /etc/motd to screen after a successful login. Either "yes" or "no". The default is "no".

This option is only available for login_duo.

prompts Optional

If a user fails to authenticate with a second factor, Duo Unix will prompt the user to authenticate again. This option sets the maximum number of prompts that Duo Unix will display before denying access. Must be 1, 2, or 3. Default is 3.

For example, when prompts = 1, the user will have to successfully authenticate on the first prompt, whereas if prompts = 2, if the user enters incorrect information at the initial prompt, he/she will be prompted to authenticate again.

When configured with autopush = yes, we recommend setting prompts = 1.

accept_env_factor Optional

Look for factor selection or passcode in the $DUO_PASSCODE environment variable before prompting the user for input. When $DUO_PASSCODE is non-empty, it will override autopush.

The SSH client will need SendEnv DUO_PASSCODE in its configuration, and the SSH server will similarily need AcceptEnv DUO_PASSCODE.

Example: $ DUO_PASSCODE=push ssh test@


Push a login request to your device.


Authenticate via phone callback.


Get a new batch of SMS passcodes. Your login attempt fails — log in again with one of your new passcodes.

A numeric passcode

Log in using a passcode, either generated with Duo Mobile, sent via SMS, generated by your hardware token, or provided by an administrator.

You can also add a number to the end of these factor names if you have more than one device registered. For example, push2 will send a login request to your second phone, phone3 will call your third phone, etc.

Default is "no".

This option is only available for login_duo.

fallback_local_ip Optional

Duo Unix reports the IP address of the authorizing user, for the purposes of authorization and network allow/deny. If Duo Unix cannot detect the IP address of the client, setting fallback_local_ip = yes will cause Duo Unix to send the IP address of the server it is running on.

If you are using Authorized Networks, enabling this option could cause unauthorized logins if the local IP is listed in the allow list.

https_timeout Optional

Set to the number of seconds to wait for HTTPS responses from Duo Security. If Duo Security takes longer than the configured number of seconds to respond to the preauth API call, the configured failmode is triggered. Other network operations such as DNS resolution, TCP connection establishment, and the SSL handshake have their own independent timeout and retry logic.

Default is 0, which disables the HTTPS timeout.

send_gecos Optional

Sends the entire GECOS field as the Duo username.

Default is "no"; the GECOS field is not used or parsed.

If you specify gecos_username_pos and gecos_delim, this setting is ignored.

gecos_username_pos Optional

Specify this option to select what position from the GECOS field will be used as the username. Positions are separated by whatever you specify in gecos_delim or the default delimiter, a comma (,).

For example, if the /etc/passwd entry for a user is:


Then setting gecos_username_pos=2 sends gecos2 as the Duo username.

If not configured, the GECOS field is not parsed for the username.

Overrides send_gecos, if set.

gecos_delim Optional

Specify this option to change the default value of the GECOS delimiter from a comma to another character. The new delimiter specified must be exactly one character, and must a valid punctuation character other than a colon (:).

For example, if the /etc/passwd entry for a user is:


Then setting gecos_username_pos=3 and gecos_delim=/ sends gecos3 as the Duo username.

If not configured, the default comma (,) GECOS field delimiter is used.

Example configuration file with additional options:


For more information, see the man page for login_duo.

Network Diagram

  1. SSH connection initiated
  2. Primary authentication
  3. Duo Unix connection established to Duo Security over TCP port 443
  4. Secondary authentication via Duo Security’s service
  5. Duo Unix receives authentication response
  6. SSH session logged in