Getting data from my program into snmpd - snmp

I guess I have missed the obvious, maybe, but I am lost for a good answer.
I am developing a stand alone program that will be running on a Linux (Ubuntu?) embedded PC inside a piece of hardware. I want it to be the "thing" SNMP talks to. Well, short of compiling in my own SNMD "daemon" code and persuading Linux to let a general user have access to port 161, I think I'll opt for Net-SNMP's snmpd. I am open to suggestions for better products to use. LGPL, BSD, MIT, licenses, please.
I am working separately on the MIB and assigning OIDs, etc. I know what vars I want to set and get, etc.
I have read and reread the stuff on making an SNMP/snmpd Agent and/or subagent. Near as I can tell, they are both compiled into snmp or linked to it as a shared library. Right?
So, how do I get that agent to talk to my sepaprate program running in a separate general user session? Is there a direct technique to use? D-Bus? ppen()? Named pipes? Shared memory? Temp files? UDP port? Something better? Or do I really want to turn my program into a .SO and let snmpd launch it? I assume at that point I'd be abe to tell snmpd where to call in to me to get/set vars. Right?
Thanks!

The "AgentX" protocol is a way for arbitrary applications to supply SNMP services to a running system SNMP daemon. Your application listens on some port other than 161 (typically a library will take care of the details for you), and the system snmpd will forward requests for your OIDs to your subagent. This method doesn't involve linking any code into the system snmpd.
Often an easier way is to configure the system snmpd to run a script to get or set data. The script can, if you like, use some other kind of IPC to talk to your application (such as JSON to an HTTP server, for example).

Related

How to trigger a script when I see that I get a SNMP Set packet

I have a something that is sending an SNMP set command to my server. I can see the packet in wireshark, and I know that I'm getting the packet. Once I get this packet I need to decode it and do an operation (using a script). I can't believe I am the first person that needs to do this, but have googled for hours and found no one else in this use case. I've seen utilities that allow me to use a get snmp, but as the set doesn't actually set anything on my server, there is no way to get it. It doesn't seem traps are helpful as that seems to find the message, as its not labeled a trap. Is there a way to convert the set to a trap once my server gets it, or is there a better method. My server is windows, but if I have to create a linux VM to make this easier I'm all ears. As of now I'm thinking powershell, but if there is an easy way in go, c#, etc I would totally do it.
I am attempting to get a SNMP SET to and use that as a trigger for running a script.
You are 100% correct in that you are not the first person to ask this question. The answer depends on which SNMP agent you have deployed. Many people have had success with Net SNMP and if you want to invoke a shell script from the SNMP agent, see this tutorial. Good luck with your project.
I ended up using pythons pysnmp to build an agent that would recieve the set/get requests. I had to compile my own MIBs for the PDU I was emulating, but got the job done. I also looked into Net SNMP, but I'm more familiar with python and found many helpful examples and good documentation.
I would like to flatten my use case, but at the moment I have two scripts, one that is the agent using pysnmp and one that will do a get request to see what the value is and set off a ssh script. I wish I could hook into the snmp set function, like when the var is written, but for now I have working setup. If anyone wants me to post my code I can.
Copied a lot of code from the second example here:
https://pysnmp.readthedocs.io/en/latest/examples/v3arch/asyncore/agent/cmdrsp/agent-side-mib-implementations.html
Learned about MIB compiling and used the mbidump.py tool. Looks like if you don't provide the proper file the old host server might be compromised and it downloads a file automatically...so be careful.

Reliable IPC With Shell Scripts

Okay, so I have two shell scripts, a server and a client, where the server is always run as root, and the clients can be run as standard users in order to communicate with the server.
The method I've chosen to do this is with a world-accessible directory containing named pipes (fifos), one of which is world-writable (to enable initial connection requests) and the others are created per-user and writable only by them (allowing my server script to know who sent a message).
This seems to work fine but it feels like it may be over-engineered or missing a more suitable alternative. It also lacks any means of determining whether the server is currently running, besides searching for its name in the output of ps. This is somewhat problematic as it means that writing to the connection fifo will hang if the server script isn't available to read from it.
Are there better ways to do something like this for a shell script? Of course I know could use an actual program to get access to more capabilities, but this is really just intended to provide secure access to a root service for non-root users (i.e - it's a wrapper for something else).
You could use Unix domain sockets instead of fifos. Domain sockets can be created with nc -lU /path/to/wherever and connected to with nc -U /path/to/wherever. This creates a persistent object in the filesystem (like a fifo, but different). The server should be able to maintain multiple simultaneous connections over the same socket.
If you're willing to write in C (or some other "real" programming language), it's also possible to pass credentials over Unix domain sockets, unlike fifos. This makes it possible for the server to authenticate its clients without needing to rely on filesystem permissions or other indirect means. Unfortunately, I'm not aware of any widely-supported interface for doing this in a shell script.

How to execute console applications on windows operating system from ruby installed on linux?

I am trying to run console application (say win_a.exe; which is having few command line parameters) from ruby script(say lin_r.rb) on linux. win_a.exe is interacting with windows services on windows server 2008. I want to run win_a.exe at particular point via lin_r.rb (reason is that, at this time; I am having few parameters those need to be passed to win_a.exe and get some result)
I searched online but I did not get any useful links.
One solution in my mind is:
create the NFS share on windows and map that to linux.
Linux: write parameter/command in a new file(should be created on NFS share) from lin_r.rb
Window: watchdog program(need to write this) looking for a new file. If found execute win_a.exe with parameters and write result to new out file.
Linux: Yey! Got result
Is this good approach? What do you think?
Thanks, Vipul
Your approach could be made to work, however If I were implementing this, I would use HTTP instead of NFS. Likely both computers involved already are capable of making and receiving HTTP requests, so the setup should be less than NFS.
The basic approach would be to have the linux based script make an HTTP request to the windows machine, with the parameters to the .exe specified as query parameters (if you use a GET request). On the windows side, your "watchdog" program would be a small web service that would respond to the request from the linux machine, execute the program with the specified options, and return the result.
The web service on the windows machine can use whatever technology you prefer. I would likely use Sinatra+Thin, but the choice is up to you.
Whichever approach you take, NFS based, HTTP based, or something else, you should make sure you give thought to security. That means that you should not blindly pass the arguments you receive from lin_r.rb to the win_a.exe program. You should only accept specific arguments, and you should make some effort to verify that the person making the request (or writing the file if you use NFS) is someone who you have authorized to have access.

Many-to-many messaging on local machine without broker

I'm looking for a mechanism to use to create a simple many-to-many messaging system to allow Windows applications to communicate on a single machine but across sessions and desktops.
I have the following hard requirements:
Must work across all Windows sessions on a single machine.
Must work on Windows XP and later.
No global configuration required.
No central coordinator/broker/server.
Must not require elevated privileges from the applications.
I do not require guaranteed delivery of messages.
I have looked at many, many options. This is my last-ditch request for ideas.
The following have been rejected for violating one or more of the above requirements:
ZeroMQ: In order to do many-to-many messaging a central broker is required.
Named pipes: Requires a central server to receive messages and forward them on.
Multicast sockets: Requires a properly configured network card with a valid IP address, i.e. a global configuration.
Shared Memory Queue: To create shared memory in the global namespace requires elevated privileges.
Multicast sockets so nearly works. What else can anyone suggest? I'd consider anything from pre-packaged libraries to bare-metal Windows API functionality.
(Edit 27 September) A bit more context:
By 'central coordinator/broker/server', I mean a separate process that must be running at the time that an application tries to send a message. The problem I see with this is that it is impossible to guarantee that this process really will be running when it is needed. Typically a Windows service would be used, but there is no way to guarantee that a particular service will always be started before any user has logged in, or to guarantee that it has not been stopped for some reason. Run on demand introduces a delay when the first message is sent while the service starts, and raises issues with privileges.
Multicast sockets nearly worked because it manages to avoid completely the need for a central coordinator process and does not require elevated privileges from the applications sending or receiving multicast packets. But you have to have a configured IP address - you can't do multicast on the loopback interface (even though multicast with TTL=0 on a configured NIC behaves as one would expect of loopback multicast) - and that is the deal-breaker.
Maybe I am completely misunderstanding the problem, especially the "no central broker", but have you considered something based on tuple spaces?
--
After the comments exchange, please consider the following as my "definitive" answer, then:
Use a file-based solution, and host the directory tree on a Ramdisk to insure good performance.
I'd also suggest to have a look at the following StackOverflow discussion (even if it's Java based) for possible pointers to how to manage locking and transactions on the filesystem.
This one (.NET based) may be of help, too.
How about UDP broadcasting?
Couldn't you use a localhost socket ?
/Tony
In the end I decided that one of the hard requirements had to go, as the problem could not be solved in any reasonable way as originally stated.
My final solution is a Windows service running a named pipe server. Any application or service can connect to an instance of the pipe and send messages. Any message received by the server is echoed to all pipe instances.
I really liked p.marino's answer, but in the end it looked like a lot of complexity for what is really a very basic piece of functionality.
The other possibility that appealed to me, though again it fell on the complexity hurdle, was to write a kernel driver to manage the multicasting. There would have been several mechanisms possible in this case, but the overhead of writing a bug-free kernel driver was just too high.

How do I check the destination that a socket is connected to?

If,for example,The socket in my compiled application is designed to connect to 123.456.789.0.
How do I check if its connected to 123.456.789.0? Is there a way to do this?
The idea is this:I want to prevent other people editing my program and changing the address to,for example, 127.0.0.1 and make it connect through a proxy.
Is there any function/way/trick to check the address after the socket is connected?
Use the getpeername function to retrieve the address of the remote host.
If someone edits your program like you mention, they'll probably alter such a check as well though.
nos's comment about the insecurity of this approach is correct, but incomplete. You wouldn't even need to change the program's code to circumvent your proposed mechanism.
The easiest way around it would be to add an IP alias to one of the machine's network interfaces. Then a program can bind to that interface on the port your program connects to, and the OS's network stack will happily send connections to the attacker's local program, not your remote one.
So, now you say you want to know how to list the computer's interfaces so you can detect this sort of subversion. Your opponent counterattacks, launching your program as a sub-process of theirs after installing a Winsock hook that routes Winsock calls back through the parent process.
We then expect to find you asking how to read the executable code section of a particular DLL loaded into your process space, so you can check that the code is what you expect. Now your opponent drops the Winsock shim, switching to an NDIS layer filter, rewriting packets from your program right before they hit the NIC.
Next we find you looking for someone to tell how to list the drivers installed on a Windows system, so you can check that one of these filters isn't present. Your opponent thinks for about 6 seconds and decides to start screwing with packet routing, selecting one of at least three different attacks I can think of off the top of my head. (No, wait, four.)
I'm not a security expert. Yet, I've spent five minutes on this and already have your security beat seven different ways.
Are you doomed? Maybe, maybe not.
Instead of you coming up with fixes to the risks you can see, better to post a new question saying what it is you're trying to protect, and have the experts comment on risks and possible fixes. (Don't add it here. Your question is already answered, correctly, by nos. This is a different question.)
Security is hard. Expertise counts for far more in that discipline than in most other areas of computer science.

Resources