ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
In case this changes anyone's answers, both boxen involved are going to be embedded appliances over which I have 100% control over the software stack. Lightly hacking existing software is an option, I'm not using anything at all I can't get source to.
Okay, so here's the situation. I have an application which needs to routinely call commands on a remote machine. Both machines can be trusted, but the network possibly cannot be. Thus, the simplest method seemed to be to just use ssh.
In order to speed up connection times and give both boxen a break on work, I'd like to just open up an ssh session to a bourne shell and allow the client program to send its commands by writing to/from pipes attached to the ssh session.
Which leads me to a number of issues. For instance, how would one know when one command ends? As a human, I know that a command has ended when the prompt reappears, but I can't use that because stdout will contain arbitrary data. I can't conceive a situation where the output of an accessible command would include the command prompt, but it could happen.
Currently my idea for handling this involves utilizing stderr. None of the commands on the remote side need to use stderr for it's original purpose, so I'm thinking of sending the return code of each process on stderr after it ends.
However, my other problem is less easily solved. I want to be able to run code on the server like this:
Code:
cat > /path/to/file
Which I would like to call by passing the name of the script containing the above code into the ssh's pipe, then start piping data into command. But how will it know how to finish? I can't just disconnect my pipe to ssh because I'll need to run commands later.
Does anyone see a way around this? If it makes any difference, the code writing to the pipe is in C++.
Note: I'm in pre-design brainstorming. If it can't be done, that's a perfectly acceptable answer. I have little to nothing invested in this idea. If you have a better way of reaching the same goals, please let me know.
For instance, how would one know when one command ends? As a human, I know that a command has ended when the prompt reappears, but I can't use that because stdout will contain arbitrary data.
I had a similar issue to deal with once or twice. The trick I used (I was writing my own client/server code) was to encode the 'cmd' (in my case data) as its ASCII equiv values, together with some field names and send that as a msg, terminated by \n, iirc. Then I'd decode at the other end and deal with it. Enables you to send just about any char, and the encode/decode is basic/simple.
In my case I used Perl, and Perl has modules to talk over SSH.
... as its ASCII equiv values, together with some field names and send that as a msg, terminated by \n, iirc. Then I'd decode at the other end and deal with it. Enables you to send just about any char, and the encode/decode is basic/simple.
I think we are talking about different problems. The problem is not that I have an executable on client side that I would like to send to the server and run there. Any executables I would want to run on the server are already there. All I want is the ability to meaningfully delimit the output of the commands. The problem is more related to stream redirection than networking (as I understand it).
I'm beginning to think that perhaps I should just get a new ssh tunnel for each command I want to run, which drastically simplifies the problem. It just seems so wasteful to be constantly re-authenticating.
Also iirc, you can just sent straight binary over ssh. Printing it to the terminal wouldn't look very nice, but something like
Be careful using 'cat' to pipe a binary file through ssh; some character translations can happen; it would be safest to create a temporary file to copy via scp.
One thing you haven't mentioned so far is the reliability of the network connection; your code shouldn't cause any problems when the network goes down.
I don't see why you would want the client to execute something like "cat >some_file" on the server - will someone be sitting at the client or do you have a program writing to stdout and you want the output to be dumped to the server?
I can see numerous points of failure here, but I can't really comment much without knowing what your requirements are. If the network failed, would it be fine that the program running on the client couldn't send its output to the server?
The network in question is a single COTS wired ethernet router dedicated to this purpose. Everyone has a static IP. We don't touch the Internet ever (this is actually a requirement due to the fact that if this ever comes to fruition, it has the potential to carry credit card numbers.) The network probably is secure without ssh, but since it's carrying financial info, I'm taking the better-safe-than-sorry route. I'm thinking that this network should be pretty stable. In fact, always on/static IP/dedicated router/dedicated server should be about as stable as it gets in a COTS system.
Regarding passing data over ssh, in my particular instance all data passed is ASCII-encoded. I was only remarking that I thought it were possible to do the same thing with binary. You're saying that this is not the case and that ssh can distort the characters? You may be right, hrmm. I thought ssh would not translate the data if it were being pushed through a pipe and not printed to a terminal, but I'm not certain at all.
If this winds up being difficult, I'll axe the idea. The whole point of using ssh is that I thought it would be simpler than implementing my own client/server code which did the same thing. I figure the simpler I keep things, the better.
And one last detail that may make a difference - the command interpreter on the other side will probably not be bash/dash/sh, etc. It will likely be custom and small. The "commands" being run are not traditional UNIX commands, and one cannot run UNIX commands over this ssh. Rather, they will have about 6-12 special-purpose commands.
I suppose I could scp the input over and the output back, but the point of the question was to avoid the overhead of re-authenticating on each and every communication, rather to re-use an ssh connection.
Hrm, well the authentication isn't actually taking that long. It would simplify things even further to just use a separate instance of ssh for each command - indeed that would invalidate my need to even ask these questions.
If I use RSA authentication, it seems to be taking less than .25s of real time. It's not blazing, but it should be enough. It looks like I'll just re-ssh for each command. Thanks for your help guys (or gals, one never knows over the web).
Don't try too hard to make ssh do the job - work out what needs to be done then look for a good way to do it; sometimes the best solution is to sit down for 2 months and write that client/server code with some TLS implementation to secure the lines. You're right in securing the lines between any two points; I use GPRS packets to transmit a lot of data and I can't rely on the GPRS packet encryption because the packets are decrypted at the telco's gateways, which means that there is some potential for unauthorized access to the data. Corporations don't like their data ever being seen by others no matter how innoccuous the data may seem (in my case nothing more than meteorological information like air temperature, humidity, wind...)
Don't try too hard to make ssh do the job - work out what needs to be done then look for a good way to do it; sometimes the best solution is to sit down for 2 months and write that client/server code with some TLS implementation to secure the lines.
I wouldn't say that I was trying to force ssh into a job it wasn't meant for. I'm using it for it's intended purpose - secure execution of remote commands. What was hackish was trying to re-use just one ssh tunnel. I now realize that what I was worrying about was, in essence, premature optimization. I think I'll worry about the time spent on authentication when and if it becomes a problem.
Also, another reason I wished to use ssh rather than my own homebrew networking code is that, frankly, the openSSH guys have already put a lot of work into that code and I trust that OpenBSD developers have thought of things security-wise that I haven't. I'm trying to keep security and functionality orthogonal and leverage as much open-source code as possible.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.