3

I'm wondering what is the best way to manually generate a hardware key based on certain components of the machine.

Here's the thing: I want only certain type of machines to be able to communicate with my server. In order to do that, I'd like to make sure that their hardware is just part of the "allowed hardware" that my server recognizes (or accepts).

I would like to generate a key based on said hardware so I can check it on the server side and make sure that it's among the "allowed ones".

Ideally, it would "check"

  • Processor
  • Motherboard
  • Ethernet network interface

Memory and hard drive are a bit tricky, because those may change pretty often.

I am using Ubuntu 10.10 and I have seen the lshw command which provides pretty much information about... well... about everything. Also, cat /proc/cpuinfo, dmidecode... All of them show a lot of information which I can always parse with regular expressions and do... things, but I was wondering if there's a cleaner more direct way.

Any hint or suggestion in this matter will be appreciated.

Thank you.

  • 4
    In my opinion, the best answer that can be given: "don't". – Chris Down Mar 28 '12 at 18:07
2

Interesting problem which I would think is going to bite you in the end.

You can do a script that will do the following:

rm /tmp/hw_snapshot
touch /tmp/hw_snapshot
cat /proc/cpuinfo | grep <whatever> >> /tmp/hw_snapshot
dmidecode | grep <whatever> >> /tmp/hw_snapshot
lspci | grep <whatever> >> /tmp/hw_snapshot
md5sum /tmp/hw_snapshot > /tmp/key

No you have a unique identifier for your hardware configuration. The issue is that even within the same model line the hardware can vary widely including CPUs, Network Cards, Number of Network Cards, etc. So basically if someone has an HP DL380 model and then gets another one with an extra network card added your unique key is no longer valid.

Plus I still don't understand the purpose of hardware base restriction on communication. If you want to control what talks to your machine put the stuff that can on a private network with it (if you can).

  • Oh, is pretty much that I know that the devices who are going to talk to my server have a very specific software. I can't put them in a LAN or VPN, though (I've tried). I'm probably just being paranoid, but it's more like a curiosity, though :-) – BorrajaX Mar 28 '12 at 22:23
  • If that is the case then use SSH as Nils suggested and share the key between them. Or just have software generate one. – Karlson Mar 28 '12 at 23:34
  • 1
    Yeah, I'm going to do that too :-D... Speaking of paranoid... I pretty much want to avoid someone cloning one of the clients' hard drives and getting a machine for free :) – BorrajaX Mar 28 '12 at 23:36
2

While you could just create an md5sum of outputs from lspci, dmidecode etc..., this will cause problems if there is any slight hardware change (e.g. more memory or another network card is added), or even if the output from those tools changes.

Commercial software often uses the network card's MAC address for license management, but this can be forged e.g. with macchanger.

As already stated, you would be better off putting those systems in a private network with restricted access, using e.g. a VPN.

2

Key? Why do you not use SSH or VPN?

You could use the vendor-part of the MAC-address - but that can easily be faked.

0

Well... I "made an stew" with the answers you guys gave me and I got something that is working for what I need and that maybe someone might find useful. It's a Python script that connects straight to U-Dev (which is what I understand dmidecode uses internally), grabs a bunch of values and generates an SHA256 key with them. I only used information about the Network devices, the bios and the motherboard. That was good enough for me (it can be changed... U-Dev offers information about... about everything your system has)

#!/usr/bin/env python    
import hashlib
import pyudev

if __name__ == "__main__":
    retval = None
    context = pyudev.Context()
    borrajaxHardwareKey = unicode()
    for netDevice in context.list_devices(subsystem="net"):
        actualDevice = netDevice.parent
        if actualDevice is not None:
            tmpList = list()
            try:
                tmpList.append(actualDevice.attributes.asstring("vendor"))
                tmpList.append(actualDevice.attributes.asstring("device"))
            except KeyError:
                tmpList = list()
            if len(tmpList) > 0:
                borrajaxHardwareKey = u"," + borrajaxHardwareKey + u":".join(tmpList)

    dmiThingy = pyudev.Device.from_path(context, '/sys/devices/virtual/dmi/id')
    dmiThingyValidAttrs = list()
    for dmiThingAttr in ["bios_vendor", "sys_vendor", "product_name", "board_vendor", "board_name"]:
        try:
            dmiThingyVal = dmiThingy.attributes.asstring(dmiThingAttr).strip()
            if len(dmiThingyVal) == 0:
                raise KeyError()
            else:
                dmiThingyValidAttrs.append(dmiThingyVal)
        except KeyError:
            pass

    borrajaxHardwareKey = u"," + borrajaxHardwareKey + u":".join(dmiThingyValidAttrs)
    print "1) Before hashing (do not use this one):\n\'%s\'" % borrajaxHardwareKey
    borrajaxHardwareKey = hashlib.sha256(borrajaxHardwareKey).hexdigest()
    print "2) After hashing:\n%s" % borrajaxHardwareKey
  • Not sure where the idea that dmidecode uses udev came from, but that is not true. dmidecode mmap's a range in lower memory, and searches for the magic values identifying DMI / SMBIOS tables, which are written by the BIOS. Once found, those tables are parsed and output in human-readable form. Given proper kernel config (CONFIG_DMI_SYSFS, I believe), the table and entries are exposed in /sys/firmware/dmi/*, which is considerably easier than direct access to lower memory. – Mark Apr 16 '17 at 22:55

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.