On Thu, 26 Feb 2009, Rainer Gerhards wrote:

> Hi David,
>
> I think you got lost in the callbacks.

yep, that's what I meant by the 'twisty maze of helper functions'

> The multiple send calls are not for multiple actions. This is all for
> one action. That code was contributed as part of the IPv6 port. I
> verified the implementation with what I could find as references to
> sending on IPv6 and think the implementation uses proper procedures for
> that environment.
>
> In essence, on an IPv6-enabled system, you will receive multiple sockets
> that you potentially can use to send the message. What the code does is
> iterate over these sockets and see which one really works. There is also
> an option (not checked but pretty sure) that permits sending to all
> receivers. I think that was the other situation you have seen.

this I definantly don't understand. I haven't done much coding in this 
area, and most of what I have done ends up being cut-n-paste out of the 
'linux application programming' book examples (which are supposed to work 
for IPv6 as well as v4)

> The listen socket is NOT being reused for sending.

when I chased down the callback functions to find what function created 
the sockets, the only thing that I found was a routine that looked like it 
was going through the config options to create sockets for all the 
listening ports.

> RFC3164 actually
> recommends that port 514 is used as the source port, and we had a
> lengthy discussion at the IETF about this recommendation. The bottom
> line is that you cannot reuse the receive socket on a highly parallel
> syslogd because each thread needs its own (or you have even more sync).
> Rsyslog creates a new (set of) send sockets *per action*.

if you don't do a bind on the socket you can't specify the source port. if 
you do bind on the socket and set the source port to 514 aren't you 
generating a conflict between the multiple send sockets?

> I guess part of the confusion stems back from your understanding of
> sysklogd code. Sysklogd works totally different here.

probably.

> I hope this clarifies a bit. I will try to have a look at the code
> provided asap and see what I can do. Its unfortunately still very busy,
> so I can not commit when I will finally start.

thanks. I'll keep poking at this.

David Lang

> HTH
> Rainer
>
>> -----Original Message-----
>> From: [email protected] [mailto:rsyslog-
>> [email protected]] On Behalf Of [email protected]
>> Sent: Wednesday, February 25, 2009 9:47 PM
>> To: rsyslog-users
>> Subject: Re: [rsyslog] UDP source forging.
>>
>> figuring out how to do this is navigating a twisty maze of helper
>> functions, all different ;-)
>>
>> there are a few things that look odd here if I am reading the code
>> properly.
>>
>> rsyslog makes one call to the UDPSend routine for all forwarded
>> messages,
>> this means that they must all send the same format.
>>
>> the UDPSend routine then walks through all destinations attempting to
>> send
>> the message to them. and considers the message successfully sent if
> any
>> of
>> them can be sent. I would have expected that it would only be
>> considered
>> successful if all of them succeded.
>>
>> UDPSend attempts to use the sockets that were created to listening for
>> messages to send it's message out. in a multi-homed machine the local
>> IP
>> address of those sockets may not be appropriate for the relay. also,
>> what
>> would happen if a system recieves via TCP and forwards via UDP and so
>> doesn't have any UDP listener sockets.
>>
>>
>> so now, my suggestion
>>
>> On Linux in /etc/sysctl.conf add the line
>>
>> net.ipv4.ip_nonlocal_bind=1
>>
>> this tells the kernel not to fail bind requests to IP addresses that
>> don't
>> exist on the box
>>
>> then in omfwd.c
>>
>> in the routine that calls UDPSend, modify it to pass the source IP
>> address
>> of the message to UDPSend
>>
>> create a new filehandle array to use for outbound messages (one
>> filehandle
>> for each destination since they may end up with different source IPs)
>>
>>
>> in UDPSend
>>
>> three options.
>>
>>
>> 1. default
>>
>>    use the appropriate filehandle for each destination and send the
>> message. this is similar to what currently takes place, but instead of
>> walking through each open socket for each destination, there should
>> only
>> be one sendto per destination. when opening the socket it should not
> be
>> nessasary to do a bind, just issue the socket call.
>>
>>    if there is anything in the syslog standard specifying the source
>> port
>> (I don't think there is, although many implementations use port 514
>> becouse they do the same thing that rsyslog is doing and re-use
>> listening
>> sockets to send messages)
>>
>>
>> 2. randomize source ports to support external load balancers
>>
>>    same as default, except that every X (configurable) messages close
>> and
>> re-open the sockets.
>>
>>    the reason for this is that each time a message is first sent the
> OS
>> picks a random source port that will be used for all messages sent
>> through
>> that socket. by closing the socket once in a while, load balancers
> that
>> balance based on source IP + source port + destination IP +
> destination
>> port will be able to function (a similar feature for TCP based
>> transports
>> would be useful for the same reason)
>>
>>
>> 3. forge the source IP/port
>>
>>    for each message that is sent, open a new socket, then issue a
>> 'bind'
>> command for that socket (filehandle) that sets the local IP address to
>> the
>> IP address that the message initially came from, then issue the
> sendto,
>> then close the filehandle.
>>
>>    there is no need for an array of sockets in this case as the socket
>> needs to be re-opened for each message/destination. in theory there is
>> a
>> possibility of a performance gain by keeping sockets open and re-using
>> them, but since each socket is unique to the sender + destination
> there
>> would be a large number of sockets and a low probability of re-using a
>> socket for the next message.
>>
>> in sysklogd I implemented #2 with the simple code below (once I
> created
>> a
>> different filehandle to use for outbound connections)
>>
>> this closed and re-opened the socket for each message, doing it every
> X
>> messages would save on the overhead and be just as good in practice.
>>
>> the bind command that's commented out is basicly what would be needed
>> for
>> #3, but with real values for the source.sin_addr.s_addr (and
>> source.sin_port if you wanted to forge the port as well, leaving it
>> zero
>> lets the OS pick a port number)
>>
>> if (finet >0) {
>>          /* close and re-open the outbound socket after each message
> so
>> that the source port is randomized and load balancers can distribute
>> the messages */
>>          close(finet);
>>          finet = create_inet_socket();
>>          /* if we want to forge the source IP for the outbound
> packets,
>> this is the place to do it by seeting the IP address to the address we
>> received the message from
>>                  struct sockaddr_in source;
>>                  source.sin_addr.s_addr = 0x00000000;
>>                  source.sin_port = 0x0000;
>>                  bind(finet,(struct sockaddr *)
>> &source,sizeof(source));*/
>> }
>>
>>
>> the create_inet_socket() routine is:
>>
>> static int create_inet_socket()
>> {
>>          int fd, on = 1;
>>          int sockflags;
>>
>>          fd = socket(AF_INET, SOCK_DGRAM, 0);
>>          if (fd < 0) {
>>                  logerror("syslog: Unknown protocol, suspending inet
>> service.");
>>                  return fd;
>>          }
>>
>>          if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
>>                         (char *) &on, sizeof(on)) < 0 ) {
>>                  logerror("setsockopt(REUSEADDR), suspending inet");
>>                  close(fd);
>>                  return -1;
>>          }
>>          /* We must not block on the network socket, in case a packet
>>           * gets lost between select and recv, otherise the process
>>           * will stall until the timeout, and other processes trying
> to
>>           * log will also stall.
>>           */
>>          if ((sockflags = fcntl(fd, F_GETFL)) != -1) {
>>                  sockflags |= O_NONBLOCK;
>>                  /*
>>                   * SETFL could fail too, so get it caught by the
>> subsequent
>>                   * error check.
>>                   */
>>                  sockflags = fcntl(fd, F_SETFL, sockflags);
>>          }
>>          if (sockflags == -1) {
>>                  logerror("fcntl(O_NONBLOCK), suspending inet");
>>                  close(fd);
>>                  return -1;
>>          }
>>          return fd;
>> }
>>
>>
>> this isn't a patch like you asked for and I offered to put togeather,
>> but
>> is it enough to clearly explain this? if not I can continue to work on
>> the
>> patch.
>>
>> David Lang
>>
>> On Tue, 24 Feb 2009, Rainer Gerhards wrote:
>>
>>> David,
>>>
>>> Excellent, please do as you have time. I'll make sure it fits.
>>> Thread-safety, btw., is not a big issue at this level as the output
>>> modules are guaranteed to be never called by multiple threads
>>> concurrently. That was a trade-off to enable other folks to easily
>> write
>>> them (but I have an option in the back of my head that a module can
>> tell
>>> the engine it *is* capable to run on multiple threads
>> concurrently...).
>>>
>>> Rainer
>>>
>>>> -----Original Message-----
>>>> From: [email protected] [mailto:rsyslog-
>>>> [email protected]] On Behalf Of [email protected]
>>>> Sent: Tuesday, February 24, 2009 9:43 AM
>>>> To: rsyslog-users
>>>> Subject: Re: [rsyslog] UDP source forging.
>>>>
>>>> On Tue, 24 Feb 2009, Rainer Gerhards wrote:
>>>>
>>>>> Hi David et all,
>>>>>
>>>>> Currently rsyslog does not support this and I have to admit I was
>>>> always
>>>>> very hesitant to add it (I see potential for misuse). Co-
>>>> incidentally, I
>>>>> received a similar request and was about to relay it to the
> mailing
>>>> list
>>>>> to gather feedback. As it looks, this no longer is necessary ;)
>>>>>
>>>>> When I thought about implementation, I originally thought about
> raw
>>>>> sockets (which indeed require root access), but if there is any
>>> other
>>>>> way, I would be most interested. If you can provide some code, I
>>> will
>>>>> happily integrate it. I think an addition to the omfwd module, in
>>> udp
>>>>> forwarding, together with a new directive
> ($SpoofOriginalUDPAddress
>>>> or
>>>>> so...) would be the right way to go.
>>>>
>>>> I'll see about hacking in some example code (probably without any
>>>> config
>>>> option and not thread-safe) and send it to you.
>>>>
>>>> there's another similar change in the same area that I was looking
>> at,
>>>> I'll mock it up as well.
>>>>
>>>> David Lang
>>>>
>>>>> Rainer
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: [email protected]
>>>>>> [mailto:[email protected]] On Behalf Of
>>>> [email protected]
>>>>>> Sent: Tuesday, February 24, 2009 4:40 AM
>>>>>> To: rsyslog-users
>>>>>> Subject: Re: [rsyslog] UDP source forging.
>>>>>>
>>>>>> On Mon, 23 Feb 2009, RB wrote:
>>>>>>
>>>>>>> On Mon, Feb 23, 2009 at 18:11,  <[email protected]> wrote:
>>>>>>>> I have a need to use some products that are stupid enough
>>>>>> to ignore the
>>>>>>>> host field in the syslog message and instead base
>>>>>> everything on the IP
>>>>>>>> address the message originates from.
>>>>>>>>
>>>>>>>> some other syslog servers can handle this by forging the
>>>>>> source of the UDP
>>>>>>>> packet, can rsyslog do this?
>>>>>>>
>>>>>>> So is rsyslog originating the messages, or are you using it to
>>>>>>> aggregate them and then feed them on to the other [bad]
>>>>>> acceptors?  I
>>>>>>> am unaware of a way to get rsyslog to forge packets (short
>>>>>> of writing
>>>>>>> an output module), but unless you must get another syslog
>>>>>> daemon into
>>>>>>> the mix, you may be better off just feeding your messages
>>>>>> directly to
>>>>>>> the other collector.
>>>>>>
>>>>>> rsyslog would be the relay from one non-routed network to another
>>>>>> non-routed network.
>>>>>>
>>>>>> this could be a fairly simple change to the UDP output module
>>>>>> (adding a
>>>>>> couple commands around the sending of a message), but before
>>>>>> I dove in to
>>>>>> do that I wanted to see if I had missed this feature anywhere.
>>>>>>
>>>>>> David Lang
>>>>>> _______________________________________________
>>>>>> rsyslog mailing list
>>>>>> http://lists.adiscon.net/mailman/listinfo/rsyslog
>>>>>> http://www.rsyslog.com
>>>>>>
>>>>> _______________________________________________
>>>>> rsyslog mailing list
>>>>> http://lists.adiscon.net/mailman/listinfo/rsyslog
>>>>> http://www.rsyslog.com
>>>>>
>>>> _______________________________________________
>>>> rsyslog mailing list
>>>> http://lists.adiscon.net/mailman/listinfo/rsyslog
>>>> http://www.rsyslog.com
>>> _______________________________________________
>>> rsyslog mailing list
>>> http://lists.adiscon.net/mailman/listinfo/rsyslog
>>> http://www.rsyslog.com
>>>
>> _______________________________________________
>> rsyslog mailing list
>> http://lists.adiscon.net/mailman/listinfo/rsyslog
>> http://www.rsyslog.com
> _______________________________________________
> rsyslog mailing list
> http://lists.adiscon.net/mailman/listinfo/rsyslog
> http://www.rsyslog.com
>
_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com

Reply via email to