Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for agentd/maild when ipv6 is disabled and/or hostnames are used instead of IPs #1698

Merged
merged 51 commits into from
May 9, 2019

Conversation

ddpbsd
Copy link
Member

@ddpbsd ddpbsd commented Apr 23, 2019

After a number of networking changes were made to better handle IPv6, some hosts
(linux specifically) seem to have issues with networking. This seems to be more
prevalent on systems where IPv6 has been disabled. The chroot(8) has also added
complications.
One work-around has been to copy the /etc/resolv.conf to ossec/etc which has
helped a number of people, but it doesn't seem to work for everyone.

Proposed solution:
Fork off a second maild/agentd process for DNS lookups. This process would run as
the OSSEC user the original process runs as (ossecm for maild, ossec for agentd
by default). It will not be chrooted.
The 2 processes communicate via a socketpair(2) and the OpenBSD
imsg(3) framework. This is currently being used in
a number of OpenBSD utilities for communicating between processes that require different
privileges.

ossec-agentd:
ossec-agentd will fork off the dns process. When a connection is attempted, it forwards
the information to the dns process. This process will then use OS_ConnectUDP() to attempt
communication with the OSSEC server, just like ossec-agentd did previously. The socket
created for this is then passed back to the original agentd process for use.

ossec-maild:
ossec-maild will fork off the dns process, and periodically fork OS_Sendmail() processes
to send alert emails. This sendmail process would then communicate with the dns process, sending
it the mail->smtpserver. The dns process will perform the getaddrinfo, connect to the server,
and pass the connected socket back to the sendmail process for actually sending the mail.

All of this does add complexity and libevent has been added as a dependency.

Other possible solutions that I did not explore:

  • Remove the chroot(8). This isn't going to happen, it's an important part of the
    privilege separation scheme in use by OSSEC.

  • Static compilation. This doesn't help with the /etc/resolv.conf issue, but
    would help with making sure the processes can perform a getaddrinfo(3) even in the
    chroot (after /etc/resolv.conf is copied to the chroot). Unfortunately, I don't
    think this is possible on Linux due to its support for various things (nss switch
    maybe?). Statically linking against musl might work, but I haven't looked into it.

Tested on:

  • OpenBSD/amd64 (various versions)
  • OpenBSD/arm64 (various versions)
  • CentOS 7.x/amd64
  • OpenSuse 15.0

I'm sure there are bugs, edge cases, and other oddities in the code. It's been running successfully for me,
but I don't have a huge variety of systems in use. I'm also sure there are places that just need to be cleaned
up. Error messages should probably go in src/error_messages/error_messages.h, there's probably some left over
debugging stuff in there, etc.

[ddp@c7-0 ~]$ uname -a
Linux c7-0 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[ddp@c7-0 ~]$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

ddp@suse:~> uname -a
Linux suse 4.12.14-lp150.12.48-default #1 SMP Tue Feb 12 14:01:48 UTC 2019 (268f014) x86_64 x86_64 x86_64 GNU/Linux
ddp@suse:/etc> cat SUSE-brand
openSUSE
VERSION = 15.0

Should fix Issue #1145 and probably others.

ddpbsd and others added 30 commits March 11, 2019 07:10
Be able to fork a process to do dns lookups. This process will not
be chrooted, but will run as the ossec user.
It receives communicates with other daemons via imsg(3) from the
OpenBSD project. A dnslookup is performed, and a connect call is made.
If it succeeds, the fd is sent back to the calling process.
There is probably a lot of debugging stuff in this right now, and
it's very smtp specific. I hope to clean this up later. I also have
not tested this with ipv6 at all.
Try using os_dns to do dns lookups for maild.
dns_request -> os_dns_request to make it less likely to conflict
anywhere.
os_dns_error - Pass more information on dns failures.
Allow the os_dns daemon to know what called it.
-lutil is necessary on OpenBSD for imsg, and make sure libevent
is linked as well.
Untested elsewhere so far.
lf->mon and lf->hour are strings, if(lf->mon) apparently doesn't work.
Make sure they're present with strnlen.
Also, put some parentheses around some strcmp checks.
Get rid of some debugging merrors.
Allow the daemon that forks the dns process to set the name of the
process.
Move some merrors to debugs.
Add the protocol (just "smtp" for now really). Hopefully this will
me use this for something other than maild in the future.
Not sure why using dnsr.protocol isn't working, but I'll get to that
later.
I still have to look into how this should be different since it's udp
instead of tcp.
Much like maild, agentd will fork a process to do dns lookups.
The dns daemon won't fall under the chroot, so there shouldn't be
any issues with shared libraries or resolv.conf not existing in the
chroot.
An AGENT_REQ message will make os_dns try to connect to the server.
It's using the OS_ConnectUDP stuff that's already done. It should pass
a socket back to agentd for the actual connection.
This is needed everywhere except WIN32. Not my dumbest mistake, but
close. Today at least.
imsg.h gets included in includes of includes in a lot of places.
The return 0 isn't part of the if block, fix indentation and put
braces on the if.
Use the ossec user when CLIENT, ossec when not.
ibufs need to travel.
ddp and others added 21 commits March 21, 2019 12:43
This should simplify things a bit, making sure the right bits are used.
Also, make sure the correct fd is attempted to be used in imsg_init.
The logic changed a bit at some point, and the code didn't keep up
with the change. I was originally using a_sock for the socket, but
eventually just used agt->sock. Change the code to reflect that logic
change.
This is officially passing messages to the ossec server now.
I need to put an actual error into this though, instead of just
floundering. I'll figure it out eventually.
There's still a lot to do before this could be considered passable.
Used && instead of &, so fix that.
I think this will help with killing the process using ossec-control.
Enable PCRE2_SYSTEM, disable JIT, enable DEBUG.
I usually set all of these manually for testing, but got lazy. I'll
try to remember to revert when I submit a PR.
for now. I don't know if they're necessary.
Add a warning to maild to warn on max emails per hour being reached.
Bump the copyrights on the maild files, add my copyright to os_dns.c
@atomicturtle atomicturtle merged commit 498a084 into ossec:master May 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants