I use two factor authentication for OpenVPN, and I am doing that using the static-challenge directive.

I also want to store my VPN username and password.

I tried doing this using auth-user-password up per the man page, but when I do that, it doesn't give me an opportunity to offer a static-challenge, so that fails.

I tried writing a python script that would pass a username, password, and challenge response via stdin to the openvpn process, but openvpn doesn't seem to get any of the things I send to stdin (even though running the same code against a sample script I wrote that gets input using sys.stdin.readline() worked). A snippet is below.

openvpn = subprocess.Popen(                                                      
        ['openvpn', '--config', os.path.expanduser('~/.ovpn-config')],           
openvpn.communicate('%s\n%s\n%s\n' % (username, password, otp))                  

Any thoughts on how to both store the username and password and use a static challenge?



I guess the problem is, that the username and password are not sent via stdin!

You should take a look at the python module "pexpect".


You have to use a pseudo tty:

#!/usr/bin/env python

import os
import sys
import pty
import subprocess

OVPN = "client.ovpn"

p = subprocess.Popen(["oathtool", "--totp", "-b", K], stdout=subprocess.PIPE)
code = p.stdout.read().strip()

cp, fd = pty.fork()
if cp == 0:
    os.execlp("openvpn", "openvpn", "--config", OVPN)
    f = os.fdopen(fd)
    challenge = False
    while not challenge:
        l = os.read(fd, len(CHALLENGE))
        challenge = l == CHALLENGE
        if not challenge:
    os.write(fd, "%s\n" % code)
    while True:
            print f.readline().strip()
        except KeyboardInterrupt:
            os.kill(cp, 15)
        except IOError:
            print "Bye"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.