Git Product home page Git Product logo

llmnrd's Introduction

llmnrd - Link-Local Multicast Resolution Daemon

GitHub Action Status Coverity Status

llmnrd is a daemon implementing the Link-Local Multicast Name Resolution (LLMNR) protocol according to RFC 4795. It currently only supports Linux, as it uses the netlink kernel interface.

llmnrd will respond to name resolution queries sent by Windows clients in networks where no DNS server is available. It supports both IPv4 and IPv6.

Installation

To build and install llmnrd use the following commands:

$ make
$ sudo make install

By default, the llmnrd binary will be installed to /usr/local/sbin. To install the binary to a different installation path, use:

$ make
$ sudo make prefix=<path> install

Cross-Compilation

To cross-compile llmnrd for a different architecture, set the CC make variable to the corresponding cross-compiler. To e.g. build it using the arm-linux-gnueabihf toolchain use:

$ make CC=arm-linux-gnueabihf-gcc

When cross-compiling, you usually don't want to install the generated binary to your root filesystem, but to the sysroot of a cross-compiled system. Use the DESTDIR variable to change the installation destination path, e.g.

$ make DESTDIR=$HOME/sysroot/ prefix=/usr install

Usage

To run llmnrd in the default mode (listening on UDP port 5355):

$ llmnrd

By default, LLMNR name resolution is only possible over IPv4. To additionally enable LLMNR name resolution over IPv6 use:

$ llmnrd -6

Use llmnrd --help to show additional usage information.

Additionally, the llmnr-query utility is shipped together with llmnrd and can be used to send customized LLMNR queries:

$ llmnr-query <hostname>

Use llmnr-query --help to show additional usage information.

License

llmnrd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License.

llmnrd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

Please see the COPYING file for the full license text.

Contributors

llmnrd is authored and maintained by Tobias Klauser [email protected]

The following people contributed patches and ideas, found and reported bugs or otherwise helped in the development of llmnrd:

  • Diego Santa Cruz (@diego-santacruz)
  • Elazar Leibovich (@elazarl)
  • Martin Hauke
  • Michael Evertz (@dvl-mevertz)
  • Pali Rohár
  • @Schimmelreiter
  • @svimik
  • @tbetker

Thanks a lot!

References

llmnrd's People

Contributors

diego-santacruz avatar dvl-mevertz avatar elazarl avatar jvfranklin avatar mpvader avatar schimmelreiter avatar tklauser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

llmnrd's Issues

Race condition since e3d021b

Seems that e3d021b introduced race condition which cause that sending SIGINT does not have to stop llmnrd daemon. I was able to reproduce it with strace and CTRL+C (but not every run!).

$ strace -f ./llmnrd
execve("./llmnrd", ["./llmnrd"], [/* 68 vars */]) = 0
...
clone(Process 3842 attached
child_stack=0x7f4682b7aff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f4682b7b9d0, tls=0x7f4682b7b700, child_tidptr=0x7f4682b7b9d0) = 3842
[pid  3841] select(4, [3], NULL, NULL, NULL <unfinished ...>
[pid  3842] set_robust_list(0x7f4682b7b9e0, 0x18) = 0
[pid  3842] socket(PF_NETLINK, SOCK_RAW, 0) = 4
[pid  3842] bind(4, {sa_family=AF_NETLINK, pid=0, groups=00000011}, 12) = 0
...
[pid  3842] recvfrom(4, "\24\0\0\0\3\0\2\0\0\0\0\0\1\17\0\0\0\0\0\0", 8192, 0, NULL, NULL) = 20
[pid  3842] recvfrom(4, ^C <unfinished ...>
Process 3842 detached
Interrupt received. Stopping llmnrd.
Interrupt received. Stopping llmnrd.

And llmnrd was still running:

$ strace -p 3842 
Process 3842 attached - interrupt to quit
recvfrom(4, "@\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\2\0\0\0C\20\1\0\0\0\0\0"..., 8192, 0, NULL, NULL) = 64
close(4)                                = 0
madvise(0x7f468237b000, 8368128, MADV_DONTNEED) = 0
_exit(0)                                = ?
Process 3842 detached

recvfrom() finished after few seconds. 3842 was second thread for netlink. Main process was still running.

$ strace -p 3841
Process 3841 attached - interrupt to quit
select(4, [3], NULL, NULL, NULL
)        = 1 (in [3])

I sent llmnr query and main llmnrd process (3841) finally finished:

recvmsg(3, ..., 0) = 31
sendto(3, ...) = 60
close(3)                                = 0
exit_group(0)                           = ?
Process 3841 detached

So it is needed to correctly and race-free handle signals in multithreaded llmnrd daemon and also correctly stop that second nelink thread.

Make a release?

Hello @tklauser! I've been distracted for a long time; but now back at the original purpose: adding your llmnrd to Venus OS.

For building I need the latest patches: can you tag & release a new version?

Thanks in advance.

Respond to multiple names

With limited amount of changes it would be possible to respond to more than just one name request. As far as I understood RFC 4795 it is also not forbidden for a single IP to be represented by multiple names.

The scenario I'm thinking of is, that a system has a generic name, ie "my-device.local" and a specific name "my-device-some-serial-number.local". This works with mdns, but not with this llmnr implementation.

The "--hostname" / "-H" parameter could be given multiple times.

Implementation idea:

If compiled with N=1 which matches current behaviour, there is only a little run-time overhead in llmnr_name_matches when the loop counter variable is evaluated.

WDYT?

If the idea sounds right to you, I could make a first draft MR.

Add support for creating pidfile

Currently llmnrd daemon supports option --daemonize which forks to background, but does not create pidfile to verify to later verify if is still running.

llmnrd: consider restricting daemon privilegies via systemd service directives

Hi.

Still not very familiar with llmnrd, but would be nice to have it tightly restricted to limit potential attack surface. This can easily be done via systemd Protect*, Restrict*, etc directives.

See https://www.youtube.com/watch?v=hiW8eIdcRgo

I haven't (yet) read the source of llmnrd, but took a guess at what you might want to add under the [Service] section:

ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectControlGroups=true
PrivateTmp=true
PrivateDevices=true
PrivateNetwork=false
PrivateUsers=true
#RootDirectory=.... to chroot
RestrictAddressFamilies=AF_NETLINK AF_INET AF_INET6
ProtectKernelModules=true
MemoryDenyWriteExecute=true

For full explanation of these please see https://www.freedesktop.org/software/systemd/man/systemd.directives.html

Conflict resolution required?

Hi, for our application, the device that we want easily accessible from Windows will in most cases be alone in the local network. And I'd prefer to give it a simple name, for example product-name. Rather than a serial-number or similar.

In a small percentage of the installs there will be multiple in one network. Meaning that there are multiple devices all responding to the same name in the network. Ie they will all reply on the llmnr request.

I tested this, with two devices, and Windows 8.1, and it works fine. In Wireshark I see two replies, and one if them (in my test the first reply, which makes sense) is the one that shows up in the browser. Which is fine for our use case.

Is there any problem you see in having multiple devices respond to the same name? Clients crashing, networks going a-wall, or anything similar?

Debian packaging files

Hi,

Are you interested with a PR adding debian folder to enable deb file packaging?

This would allow users to run debuild from the root directory and create a debian package.

And thanks for the great work. Debian Jessie's systemd doesn't have LLMNR yet, and your project makes it much easier to add LLMNR for a linux box.

llmnrd daemon should not use busy waiting for packets

Currently llmnrd daemon sleeps just for 50 miliseconds period and after that every time it check for incomming packet. In most cases there will be no incomming event and so in 99% time this daemon uses CPU just for waiting for packets. Daemon should wait in select syscall for infinite period of time and only incomming event (either packet or signal) should wake it up.

$ strace ./llmnrd
...
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
select(4, [3], NULL, NULL, {0, 50000})  = 0 (Timeout)
...

Empty AAAA response when ipv6 is not enabled

Just caught a packet that doesn't look right. I guess it should ignore AAAA requests if ipv6 is not enabled. And it shouldn't send response when it has no IP address of given type :)

llmnrd_empty_response

bind to specific interface option requires root privileges

Trying to use the -i option to bind to a specific interface fails unless it's running as root:
[jon@jonf llmnrd]$ ./llmnrd -H idrac -i ens192
Starting llmnrd on port 5355, hostname idrac
Binding to interface ens192
Error: Failed to bind socket to device ens192: Operation not permitted
[jon@jonf llmnrd]$ sudo ./llmnrd -H idrac -i ens192
[sudo] password for jon:
Starting llmnrd on port 5355, hostname idrac
Binding to interface ens192
Added IPv4 address 100.69.127.109 on interface ens192

I've tracked this down to the use of the SO_BINDTODEVICE socket option. I've got a patch I can submit for this.

llmnrd: consider starting as non-root by default in systemd service example

Hi.

Not very familiar with llmnrd right now, but reading #4 makes me think llmnrd does not need to (or even should not?) be started as root. Thus please consider using the User= and Group= directives in the shipped etc/llmnrd.service file.

(Even better would probably be to have a dedicated user/group, but I don't see how you as upstream could do that. You probably need to leave that integration to distro maintainers. Thus shipping an example using User=nobody and Group=nogroup is probably the best you can do. That user/group should be available on all distros by default I assume.)

Add support for CPPFLAGS in Makefile

Currently Makefile ignores CPPFLAGS variable and so any defines passed by build process are ignored. E.g. running make CPPFLAGS="-D_FORTIFY_SOURCE=2" does not compile llmnrd with buffer overflow checks.

llmnrd: Detect hostname changes

If the hostname is changed, e.g., by the hostname command, llmnrd will still use the old one. We can poll /proc/sys/kernel/hostname to get notified if the hostname is written, though; systemd does this as well.

See the attached patch for suggestions. It is more of a hack for now (and probably has to be restructured), but it works for us.

llmnrd-poll-hostname.patch.txt

IPv6 part is not working

Starting llmnrd on port 5355, hostname quadbox
Added IPv4 address 127.0.0.1 on interface lo
Added IPv4 address 192.168.75.17 on interface eth0
Added IPv6 address ::1 on interface lo
Added IPv6 address fd... on interface eth0
Error: Failed to join IPv6 multicast group on interface eth0: Address already in use
Added IPv6 address 2001:... on interface eth0
Error: Failed to join IPv6 multicast group on interface eth0: Address already in use
Added IPv6 address fe80::... on interface eth0

Nothing is using Port 5355, there neither are connections stuck in CLOSE_WAIT

Also there is a quirk when querying for type ANY:

root@linux ~ # llmnr-query -6 windows
LLMNR query: quattro IN ANY
LLMNR response: quattro IN AAAA 2001:... (TTL 30)
LLMNR response: quattro IN AAAA fd.. (TTL 30)
LLMNR response: quattra IN AAAA 0:8000:1:4::567:8961 (TTL 30)

When doing a type ANY query, the fe80 response gets borked.
This does not happen when doing A and AAAA queries seperately.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.