devxlogo

Control Your Linux Server Remotely with GnuPG, procmail, and PHP

Control Your Linux Server Remotely with GnuPG, procmail, and PHP

ow many times has this happened to you: you want to access a remote server, but you can’t because it is behind a firewall? I frequently found myself in such a situation when I needed to access my Internet-connected server running Linux, so I thought of a system where I could start controlling my server remotely via a simple email.

Of course, this solution had one crucial requirement: it had to be secure. The server had to respond only to senders who were identified and authorized, and the command sent to the server, along with its related output, had to travel over the wire in encrypted form. To meet these security requirements, I used the free GNU Privacy Guard (GnuPG) and some asymmetric encryption techniques (See Sidebar 1. Asymmetric Cryptography in This Solution).

GnuPG is the open source implementation of OpenPGP security software. To implement the message encryption, I employed a patent-free algorithm contained in GnuPG called the ElGamal encryption system.

This article demonstrates how my system enables you to remotely control your server in batch mode with signed and encrypted emails. It uses a fictional, authorized e-mail sender ([email protected]) and an example remote server ([email protected]) for the sender to inquiry. The server will run Debian Linux.

The Process Schema
The following are the steps involved in the process of controlling a server via email:

  1. Create the list of all authorized command senders (e.g., [email protected]).
  2. Let the sender generate private/public key pairs with GnuPG.
  3. Generate a private/public key pair with GnuPG for the server, which has the email address [email protected].
  4. Import the sender’s public key on the server keyring and server’s public key on the sender’s keyring.
  5. Let the sender sign and encrypt the command to run remotely on the server, embed it in an email, and send it to the server address.
  6. Let the server download the email messages and process them with a script as follows:
    1. Verify whether the sender is authorized.
    2. Decrypt and run the command.
    3. Capture output from stdout and stderr, possibly killing hanging commands after a reasonable period of time.
    4. Sign and encrypt the outputs, embed them in an email, and send the answer back to the sender address.
  7. Let the sender read the server outputs, verifying and decrypting its reply.

Setting Up GnuPG
The server and all the authorized users’ machines require GnuPG installation. Download GnuPG it from its homepage. On the sender machines, you can install the Linux or Windows version of GnuPG, and a GUI helper such as GPA for Linux or Cryptophane for Windows to generate and administer the keys. For the Linux Debian server used in this example, I used the following command to install GnuPG:

apt-get install gnupg

Using Command Line GnuPG to Generate and Administer Keys
The directory where GnuPG keeps the keyring is very important and has to be kept secret. If you want to use a particular directory, you have to specify it on the command line or set the environment variable GNUPGHOME. The following generates a key pair for the server, acting as the fictitious user who acts on the server by providing replies via email:

gpg –homedir /keyring/path –gen-key...Please select what kind of key you want:   (1) DSA and Elgamal (default)   (2) DSA (sign only)   (5) RSA (sign only)Your selection? 1DSA keypair will have 1024 bits.ELG-E keys may be between 1024 and 4096 bits long.What keysize do you want? (2048) 1024Please specify how long the key should be valid.         0 = key does not expire        = key expires in n days      w = key expires in n weeks      m = key expires in n months      y = key expires in n yearsKey is valid for? (0) 0...Real name: MachineEmail address: [email protected]: The MachineYou selected this USER-ID:"Machine (The Machine) "...You don't want a passphrase - this is probably a *bad* idea!I will do it anyway. You can change your passphrase at any time,using this program with the option "--edit-key"....

You can change a lot of the options used in the above commands. For example, you can dictate a keysize that is not as long (1024 bits) or have no passphrase at all. The latter is usually a very bad choice, but because this example involves unmanned use of gpg, I was obliged to write down the passphrase in the script. You can use the same procedure to generate a key pair for the remote sender, in which case using a passphrase for the secret key is highly recommended.

Once the server and the users generate their keys, they have to exchange their public keys using import and export gpg commands, as follows:

gpg --export –armor –output pub.gpggpg --import /tmp/pub.gpg

Assuming the exchange of public keys between the server administrator and authorized users takes place over a trusted channel, the exchange doesn’t face the challenge of key trust.

How to Send the Command to the Server
After the server and sender keyrings are well configured, the sender takes the following steps to package the email containing the command to be run in the server:

  1. Write a file containing the command the sender chooses. For example, the file /tmp/cmd.txt with the line:
    ls -la /tmp 
  2. Sign and encrypt the file with gpg, producing the garbled file /tmp/cmd.gpg:
    gpg --homedir /path/of/your/keyring --armor --encrypt --sign --trust-model always --recipient [email protected] --default-key [email protected] --output /tmp/cmd.gpg /tmp/cmd.txt
  3. Open a mail client and write a new message to [email protected]. Use any subject and paste the contents of the file /tmp/cmd.gpg in the message body.
  4. Send the email.

To easily test the application, find a small PHP accessory script, cmsend.php, in the downloadable code. After asking for the command and the passphrase of the sender’s secret key, this script sends the email to the server using the Mail_Mime PEAR package.

Procmail: A Pretty Good Mail Filter
On the server side, the system is required to continuously download email with a program such as fetchmail running as a daemon. Then the messages have to be dispatched by the running MTA (Mail Transport Agent) to a MDA (Mail Delivery Agent) or mail filter such as procmail. Procmail, a mail filter largely used on UNIX systems, is an event-driven email processor invoked by the MTA. Because its rules are based on regular expressions, many consider procmail a complex application, but I consider regular expressions its strength.

Procmail works using a configuration file with recipes, where each recipe consists of three parts. Without going too deeply in procmail details, here are the steps required for using it in this example. If you already have a working procmail installation, you can include the required recipe by using the following statement in the existing procmail configuration file:

INCLUDERC=/path/to/your/file/with/recipe/rc.machine

Otherwise, you have to install procmail and then write the bare minimum configuration file under your home directory (file: .procmailrc). The required recipe for this example is as follows (file: rc.machine):

:0* ^To.*[email protected]| ${APPL_DIR}/cmdproc.php

This recipe tells procmail to filter all incoming emails and select those whose “To:” address matches [email protected]. These messages have to be redirected as input (piped) to a PHP script named cmdproc.php.

The Answering Process
PHP is a very good scripting language that is useful for implementing command line programs. I used it to build the core of the automatic reply system. I installed it together with the PHP PEAR library package Mail_Mime as follows:

apt-get install php5-clipear install Mail_mime

The main file, cmdproc.php in the downloadable code for this example, includes two other files:

  • inc.vars.php: This file contains the includes for PEAR libraries and some global variable assignments that are installation-specific (e.g., the SMTP server for replying and the parametric variables in Table 1).
    Table 1. Parametric Variables for Remote Server Control
    Variable Description
    $smtp_server SMTP server used by the server
    $machine_addr server email address
    $sender_addr Authorized user email address (used only in cmdsend.php)
    $gpg_homedir Path for GnuPG keyring
    $max_cmd_time Command maximum execution time
    $special_first_chr Character used in line beginning to select special commands
  • inc.util.php: This file is a little collection of utility functions to improve the readability of the main file.

As previously stated, procmail redirects the messages sent to a specific machine address to the script that reads them in an array from standard input:

$msg_arr = file("php://stdin");

Next, the procedure extracts some pieces of information from the message:

  • The sender email address (this information is used to verify the identity of the message sender analyzing the signature)
  • The signed and encrypted part of the message

The following steps are then necessary:

  1. Verify that the public key of the sender’s email address is one of those in the server keyring.
  2. Verify the real identity of the sender expressed by the signature that seals the encrypted message.
  3. Decrypt the garbled part of the message with the server’s secret key and obtain the command to run.

It is then time to run the GnuPG command gpg within the PHP script. This is possible using the Program Execution Functions (i.e., proc_* functions), which allow you to execute programs inside a PHP script with a high degree of control over input/output structures). The utility function gpg_cmd inside the file inc.util.php runs the gpg command without using any temporary files. Rather, it manages all input and output data exchanges in memory.

With the right gpg parameters, steps 1, 2, and 3 from above are checked. If all tests are passed, the command is sent to the server in the variable $cmd_arr[‘out’] (see Sidebar 2. The Problem of Hanging Commands). The command could fit into one of the following two scenarios:

  • A standard Linux command, including any executable script: The script runs this command (see std_cmd utility function) and collects the outputs (stdout and stderr) in the two variables $run_arr[‘out’] and $run_arr[‘err’]. These outputs will be separately signed and encrypted before being embedded in the body of email reply.
  • A special command: You can run special commands using a special character, which you can customize by setting the variable $special_first_chr in position 0. I use the ‘#’ character and, as an example, I implement the special command ‘get’ to ask the server to send me back a file. That is a kind of get ftp command run in batch mode. For this special case, if the file requested exists, it will be signed and encrypted before being attached to the email reply.

Final Step: Sending Replies to Sender
Sending the reply to the sender?with the outputs conveniently signed and encrypted?is the last step. The utility function used here is send_mail in the file inc.util.php, a typical usage example of Mail_Mime PEAR package. With this function, you can send an email, provided that you set the following:

  • The SMTP server
  • The array with all the email headers you desire (To:, CC:, and so on)
  • A text for the email body
  • An array of filenames and related mimetypes for all file attachments you want

During the execution, cmdproc.php fills these structures accordingly and then sends the reply email.

Reading the Server’s Response
Eventually, depending on the fetchmail polling time, the sender will receive an answer from [email protected]. The body of the message will contain two well-delimited encrypted parts representing the standard output and standard error produced by the command. You can also have additional encryption parts if this is an answer to a special command. In all cases, each part has to be pasted in a file, say /tmp/out.gpg, that can be decrypted with the following command:

gpg --homedir /path/of/your/keyring --decrypt --output /tmp/out.txt/tmp/out.txt

The following?and final?section shows how to sign and encrypt email message parts on the fly, making the remote server control system even easier.

The Finished Product Through Firefox FireGPG
The Firefox FireGPG add-on offers an interesting integration with GMail. As Figures 1 through 6 show, FireGPG has the traditional GMail interface with additional buttons that allow you to directly sign and encrypt the message body without copying and pasting.


Figure 1. FireGPG Buttons on GMail: With FireGPG, you have extra buttons when composing email in GMail.
 
Figure 2. Public Key Choice: After pushing the Sign and Encrypt buttons, you must choose the public key to encrypt the message.


Figure 3. Secret Key Choice: You must choose the secret key to sign the message.
 
Figure 4. Input the Passphrase: You must unlock the chosen secret key with a passphrase.


Figure 5. The Message Is Signed and Encrypted: The message is signed and encrypted on the fly inside the GMail interface.

As you can see in Figures 6 through 8, if you use FireGPG and GMail, you don’t need to paste anything. You can simply decrypt the message parts on the fly.

Figure 6. The Server Reply Has Arrived: The reply from the server is listed by the GMail interface.
 
Figure 7. FireGPG Additional Action: With FireGPG, you have an extra action at the end of an email to decrypt it.


Figure 8. The Server Answer: The output produced by the command sent to the server.

That’s it! You’ve now gone inside a system that you can use to control your server remotely via a simple email.
devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist