Skip to content

Instantly share code, notes, and snippets.

Last active June 26, 2024 13:28
Show Gist options
  • Save TheJJ/2394cd76d3e2c34d02e3da1bd3e489b2 to your computer and use it in GitHub Desktop.
Save TheJJ/2394cd76d3e2c34d02e3da1bd3e489b2 to your computer and use it in GitHub Desktop.
Dell iDRAC linux/mac/windows client launcher
#!/usr/bin/env python3
Dell iDRAC client launcher for Linux, macOS and Windows.
probably works with Dell iDRAC 6/7/8
Downloads needed Java files and sets up port forwarding via SSH.
example usage: ./ -J
for more info, see ./ --help
* use python3.6 or later!
* use java 8 (jre 1.8)!
(c) 2018-2019 Jonas Jelten <>
Released under GNU GPLv3 or any later version
import asyncio
import argparse
import getpass
import pathlib
import socket
import ssl
import subprocess
import sys
import zipfile
import aiohttp
def main():
cmd = argparse.ArgumentParser()
cmd.add_argument("--port", "-p", type=int, default=443,
help="https port to connect to for idrac")
cmd.add_argument("--kvmport", "-k", type=int, default=5900,
help="port for the kvm connection")
cmd.add_argument("--basedir", "-b", default="/tmp/idracvm",
help="base directory where to put in state and downloaded stuff")
cmd.add_argument("--java", default="java",
help="custom location for the java executable")
cmd.add_argument("--username", "-u", default="root",
help="idrac login username")
cmd.add_argument("--tlscheck", action="store_true",
help="do certificat validation which is disabled by default")
cmd.add_argument("--force-download", "-f", action="store_true",
help="re-download kvm viewer files and libraries")
cmd.add_argument("--dryrun", action="store_true",
help="don't actually run the viewer, but to everything else")
cmd.add_argument("--jumphost", "-J",
help="use this jumphost for relaying the connection via ssh port forwards")
cmd.add_argument("--jumpkvmport", type=int, default=0,
help="port for kvm listened on localhost by ssh")
cmd.add_argument("--jumphttpport", type=int, default=0,
help="port for idrac webinterface listened on localhost by ssh")
cmd.add_argument("--sshtimeout", type=int, default=8,
help="timeout for establishing the ssh jump host connection")
cmd.add_argument("--no-native-libs", action="store_true",
help="don't download the native libraries for input and device redirecions")
args = cmd.parse_args()
loop = asyncio.get_event_loop()
ret = loop.run_until_complete(run(args))
async def download(url, check_tls=True):
async with aiohttp.ClientSession() as session:
tls_settings = ssl.create_default_context()
# the crappy iDRACs have slightly outdated crypto...
if not check_tls:
tls_settings.check_hostname = False
tls_settings.verify_mode = ssl.CERT_NONE
async with session.get(url, ssl=tls_settings) as resp:
return await
async def download_all(mainjar, libdir, hostname, port, tlscheck=True, use_native_libs=True):
print("downloading files...")
with"wb") as fd:
content = await download('https://%s:%d/software/avctKVM.jar' % (hostname, port), tlscheck)
if use_native_libs:
if sys.platform == 'linux':
libdls = ["avctKVMIOLinux64.jar", "avctVMLinux64.jar"]
extension = ".so"
elif sys.platform == 'darwin':
libdls = ["avctKVMIOMac64.jar", "avctVMMac64.jar"]
extension = ".jnilib"
elif sys.platform == 'win32':
libdls = ["avctKVMIOWin64.jar", "avctVMWin64.jar"]
extension = ".dll"
raise Exception("running on unknown platform: %s" % sys.platform)
for dlname in libdls:
dl_lib = (libdir / dlname)
with"wb") as fd:
content = await download('https://%s:%d/software/%s' % (hostname, port, dlname), tlscheck)
except aiohttp.ClientError:
zf = zipfile.ZipFile(str(dl_lib))
print("finished downloading files.")
async def create_sec_override(path):
# write funny security overwrite file
with"w") as fd:
fd.write("# iDRAC uses disabled, outdated crypto\n")
fd.write("# we override the disabled algos to enable 3DES_EDE_CBC and SSLv3\n")
fd.write("jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224\n")
def find_port(blacklist=[]):
port = 9009
sock = socket.socket()
while True:
port += 1
while port in blacklist:
port += 1
sock.bind(('', port))
except OSError:
return port
async def run(args):
basedir = pathlib.Path(args.basedir)
hostdir = basedir / args.hostname
libdir = hostdir / "lib"
libdir.mkdir(parents=True, exist_ok=True)
java_kvmhost = args.hostname
java_kvmport = args.kvmport
java_idracport = args.port
# jumphost setup
if args.jumphost:
if args.jumphttpport:
jumpkvmport = args.jumphttpport
jumpkvmport = find_port()
if args.jumphttpport:
jumphttpport = args.jumphttpport
jumphttpport = find_port([jumpkvmport])
print("launching port forwarding...")
forward_invocation = [
"-S", "none",
"-L", "%d:%s:%d" % (jumphttpport, args.hostname, args.port),
"-L", "%d:%s:%d" % (jumpkvmport, args.hostname, args.kvmport),
"echo kay && cat",
print("$ %s" % " ".join(forward_invocation))
sshproc = await asyncio.create_subprocess_exec(*forward_invocation, stdout=subprocess.PIPE)
# wait until "kay" appears
await asyncio.wait_for(sshproc.stdout.readuntil(b"kay\n"), timeout=args.sshtimeout)
except asyncio.TimeoutError as exc:
raise Exception("failed to set up port forwards via ssh") from exc
print("port forwards established.")
# now java has to connect to localhost
java_kvmhost = "localhost"
java_kvmport = jumpkvmport
java_idracport = jumphttpport
# download java files
mainjar = (hostdir / "avctKVM.jar")
if not (mainjar.is_file() and mainjar.stat().st_size) or args.force_download:
await download_all(mainjar, libdir, java_kvmhost, java_idracport, args.tlscheck, not args.no_native_libs)
print("no need to download files")
# create security override for SSLv3
sec_overwrite_path = (hostdir / "java_security_overrides")
await create_sec_override(sec_overwrite_path)
# query password
if args.dryrun:
password = "xxx-dryrun-xxx"
password = getpass.getpass("enter idrac password: ")
print("launching viewer...")
invocation = [,
"-cp", str(mainjar),
if not args.no_native_libs:
invocation.append("-Djava.library.path=%s" % libdir)
# single = means overwrite only parts, == means overwrite all:
"" % sec_overwrite_path,
"ip=%s" % java_kvmhost,
"kmport=%d" % java_kvmport,
"vport=%d" % java_kvmport,
"user=%s" % args.username,
"passwd=%s" % password,
"helpurl=https://%s:%d/help/contents.html" % (java_kvmhost, java_idracport),
print("$ %s" % " ".join(invocation))
if args.dryrun:
ret = 0
proc = await asyncio.create_subprocess_exec(
ret = await proc.wait()
if args.jumphost:
await sshproc.wait()
return ret
if __name__ == "__main__":
Copy link

Thanks for the script!

I can't send any keyboard key presses, mouse is working. Any idea why?

Copy link

Hello thanks for the script but I have the same keyboard issue on endeavouros with :
openjdk version "20.0.1" 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9)
OpenJDK 64-Bit Server VM (build 20.0.1+9, mixed mode, sharing)
Does anyone have an idea how to fix this

Copy link

Excellent script! Running on Fedora33 I had to do some additional changes though:

1. For older DRACs I had to create a custom openssl config openssl_allow.cnf:
openssl_conf = openssl_init

ssl_conf = ssl_sect

system_default = system_default_sect

2. Download java 1.6 (available from Centos 7 repos) `wget`

3. Unpack the old java:
   `rpm2cpio java-1.6.0-openjdk-|cpio -idmv`

And then call the script like this: OPENSSL_CONF=./openssl_allow.cnf ./ --java ./usr/lib/jvm/java-1.6.0-openjdk- -f MY_HOST

This fixed the script for me.

Copy link

chisaato commented May 31, 2024

Thanks for the script!

I can't send any keyboard key presses, mouse is working. Any idea why?

I switch to Java8 (Liberica FX) and it works. using Java22 has some error about Swing/AWT, I think these exception will cause input issues.

Copy link

chisaato commented Jun 4, 2024

Hey, I have some new research
add vm=1 to arguments can enable VirtualMedia

and on idrac8 the native lib jar name is avctVMAPI_DLLLinux64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment