Bacula permits file data encryption and signing within the File Daemon (or Client) prior to sending data to the Storage Daemon. Upon restoration, file signatures are validated and any mismatches are reported. At no time does the Director or the Storage Daemon have access to unencrypted file contents.
It is very important to specify what this implementation does NOT do:
Encryption and signing are implemented using RSA private keys coupled with self-signed x509 public certificates. This is also sometimes known as PKI or Public Key Infrastructure.
Each File Daemon should be given its own unique private/public key pair. In addition to this key pair, any number of "Master Keys" may be specified -- these are key pairs that may be used to decrypt any backups should the File Daemon key be lost. Only the Master Key's public certificate should be made available to the File Daemon. Under no circumstances should the Master Private Key be shared or stored on the Client machine.
The Master Keys should be backed up to a secure location, such as a CD placed in a in a fire-proof safe or bank safety deposit box. The Master Keys should never be kept on the same machine as the Storage Daemon or Director if you are worried about an unauthorized party compromising either machine and accessing your encrypted backups.
While less critical than the Master Keys, File Daemon Keys are also a prime candidate for off-site backups; burn the key pair to a CD and send the CD home with the owner of the machine.
NOTE!!! If you lose your encryption keys, backups will be unrecoverable. ALWAYS store a copy of your master keys in a secure, off-site location.
The basic algorithm used for each backup session (Job) is:
The configuration option for enabling OpenSSL encryption support has not changed since Bacula 1.38. To build Bacula with encryption support, you will need the OpenSSL libraries and headers installed. When configuring Bacula, use:
./configure --with-openssl ...
The implementation uses 128bit AES-CBC, with RSA encrypted symmetric session keys. The RSA key is user supplied. If you are running OpenSSL 0.9.8 or later, the signed file hash uses SHA-256 -- otherwise, SHA-1 is used.
End-user configuration settings for the algorithms are not currently exposed -- only the algorithms listed above are used. However, the data written to Volume supports arbitrary symmetric, asymmetric, and digest algorithms for future extensibility, and the back-end implementation currently supports:
Symmetric Encryption: - 128, 192, and 256-bit AES-CBC - Blowfish-CBC Asymmetric Encryption (used to encrypt symmetric session keys): - RSA Digest Algorithms: - MD5 - SHA1 - SHA256 - SHA512
The various algorithms are exposed via an entirely re-usable, OpenSSL-agnostic API (ie, it is possible to drop in a new encryption backend). The Volume format is DER-encoded ASN.1, modeled after the Cryptographic Message Syntax from RFC 3852. Unfortunately, using CMS directly was not possible, as at the time of coding a free software streaming DER decoder/encoder was not available.
It is preferable to retain a secure, non-encrypted copy of the client's own encryption keypair. However, should you lose the client's keypair, recovery with the master keypair is possible.
You must:
PKI Keypair = master.keypair
Generate a Master Key Pair with:
openssl genrsa -out master.key 2048 openssl req -new -key master.key -x509 -out master.cert
Generate a File Daemon Key Pair for each FD:
openssl genrsa -out fd-example.key 2048 openssl req -new -key fd-example.key -x509 -out fd-example.cert cat fd-example.key fd-example.cert >fd-example.pem
Note, there seems to be a lot of confusion around the file extensions given to these keys. For example, a .pem file can contain all the following: private keys (RSA and DSA), public keys (RSA and DSA) and (x509) certificates. It is the default format for OpenSSL. It stores data Base64 encoded DER format, surrounded by ASCII headers, so is suitable for text mode transfers between systems. A .pem file may contain any number of keys either public or private. We use it in cases where there is both a public and a private key.
Typically, above we have used the .cert extension to refer to X509 certificate encoding that contains only a single public key.
bacula-fd.conf
FileDaemon { Name = example-fd FDport = 9102 # where we listen for the director WorkingDirectory = /var/bacula/working Pid Directory = /var/run Maximum Concurrent Jobs = 20 PKI Signatures = Yes # Enable Data Signing PKI Encryption = Yes # Enable Data Encryption PKI Keypair = "/etc/bacula/fd-example.pem" # Public and Private Keys PKI Master Key = "/etc/bacula/master.cert" # ONLY the Public Key }
Since the very beginning of Bacula (January 2000) until today (December 2005), there have been two major Bacula tape formats. The second format was introduced in version 1.27 in November of 2002, and it has not changed since then. In principle, Bacula can still read the original format, but I haven't tried it lately so who knows ...
Though the tape format is fixed, the kinds of data that we can put on the tapes are extensible, and that is how we added new features such as ACLs, Win32 data, encrypted data, ... Obviously, an older version of Bacula would not know how to read these newer data streams, but each newer version of Bacula should know how to read all the older streams.
If you want to be 100should:
1. Try reading old tapes from time to time -- e.g. at least once a year.
2. Keep statically linked copies of every version of Bacula that you use in production then if for some reason, we botch up old tape compatibility, you can always pull out an old copy of Bacula ...
The second point is probably overkill but if you want to be sure, it may save you someday.
subsection*Configuring and Testing TCP Wrappers index[general]Configuring and Testing TCP Wrappers addcontentslinetocsubsectionConfiguring and Testing TCP Wrappers
TCP Wrappers are implemented if you turn them on when configuring (./configure --
with-libwrap). With this code enabled, you may control who may
access your daemons. This control is done by modifying the file: /etc/hosts.allow. The program name that Bacula uses when applying these
access restrictions is the name you specify in the daemon configuration file.
You must not use the twist option in your /etc/hosts.allow or it
will terminate the Bacula daemon when a connection is refused.
Dan Langille has provided the following information on configuring and testing TCP wrappers with Bacula.
If you read hosts_options(5), you will see an option called twist. This option replaces the current process by an instance of the specified shell command. Typically, something like this is used:
ALL : ALL \ : severity auth.info \ : twist /bin/echo "You are not welcome to use %d from %h."
The libwrap code tries to avoid twist if it runs in a resident process, but that test will not protect the first hosts_access() call. This will result in the process (e.g. bacula-fd, bacula-sd, bacula-dir) being terminated if the first connection to their port results in the twist option being invoked. The potential, and I strees potential, exists for an attacker to prevent the daemons from running. This situation is eliminated if your /etc/hosts.allow file contains an appropriate ruleset. The following example is sufficent:
undef-fd : localhost : allow undef-sd : localhost : allow undef-dir : localhost : allow undef-fd : ALL : deny undef-sd : ALL : deny undef-dir : ALL : deny
You must adjust the daemon names to those found in the respective daemon configuration files. In these examples, the Director is undef- dir, the Storage Daemon is undef-sd, and the File Daemon is undef-fd. Adjust to suit your situation. The above example rules assume that the SD, FD, and DIR all reside on the same box. If you have a remote FD client, then the following ruleset on the remote client will suffice:
undef-fd : director.example.org : allow undef-fd : ALL : deny
where director.example.org is the host which will be contacting the client (ie. the box on which the Bacula Director daemon runs). The use of "ALL : deny" ensures that the twist option (if present) is not invoked. To properly test your configuration, start the daemon(s), then attempt to connect from an IP address which should be able to connect. You should see something like this:
$ telnet undef 9103 Trying 192.168.0.56... Connected to undef.example.org. Escape character is '^]'. Connection closed by foreign host. $
This is the correct response. If you see this:
$ telnet undef 9103 Trying 192.168.0.56... Connected to undef.example.org. Escape character is '^]'. You are not welcome to use undef-sd from xeon.example.org. Connection closed by foreign host. $
then twist has been invoked and your configuration is not correct and you need to add the deny statement. It is important to note that your testing must include restarting the daemons after each connection attempt. You can also tcpdchk(8) and tcpdmatch(8) to validate your /etc/hosts.allow rules. Here is a simple test using tcpdmatch:
$ tcpdmatch undef-dir xeon.example.org warning: undef-dir: no such process name in /etc/inetd.conf client: hostname xeon.example.org client: address 192.168.0.18 server: process undef-dir matched: /etc/hosts.allow line 40 option: allow access: granted
If you are running Bacula as a standalone daemon, the warning above can be safely ignored. Here is an example which indicates that your rules are missing a deny statement and the twist option has been invoked.
$ tcpdmatch undef-dir 10.0.0.1 warning: undef-dir: no such process name in /etc/inetd.conf client: address 10.0.0.1 server: process undef-dir matched: /etc/hosts.allow line 91 option: severity auth.info option: twist /bin/echo "You are not welcome to use undef-dir from 10.0.0.1." access: delegated
Security advice from Dan Langille:
It is a good idea to run daemons with the lowest possible privileges. In other words, if you can, don't run applications as root which do not have to be root. The Storage Daemon and the Director Daemon do not need to be root. The File Daemon needs to be root in order to access all files on your system. In order to run as non-root, you need to create a user and a group. Choosing bacula as both the user name and the group name sounds like a good idea to me.
The FreeBSD port creates this user and group for you (actually, as I write this, the port doesn't do that, but it soon will). Here is what those entries looked like on my FreeBSD laptop:
bacula:*:1002:1002::0:0:Bacul Daemon:/var/db/bacula:/sbin/nologin
I used vipw to create this entry. I selected a User ID and Group ID of 1002 as they were unused on my system.
I also created a group in /etc/group:
bacula:*:1002:
The bacula user (as opposed to the Bacula daemon) will have a home directory of /var/db/bacula which is the default location for the Bacula database.
Now that you have both a bacula user and a bacula group, you can secure the bacula home directory by issuing this command:
chown -R bacula:bacula /var/db/bacula/
This ensures that only the bacula user can access this directory. It also means that if we run the Director and the Storage daemon as bacula, those daemons also have restricted access. This would not be the case if they were running as root.
It is important to note that the storage daemon actually needs to be in the operator group for normal access to tape drives etc (at least on a FreeBSD system, that's how things are set up by default) Such devices are normally chown root:operator. It is easier and less error prone to make Bacula a member of that group than it is to play around with system permissions.
Starting the Bacula daemons
To start the bacula daemons on a FreeBSD system, issue the following command:
/usr/local/etc/rc.d/bacula.sh start
To confirm they are all running:
$ ps auwx | grep bacula root\ 63416\ 0.0\ 0.3\ 2040 1172\ ??\ Ss\ 4:09PM 0:00.01 /usr/local/sbin/bacula-sd -v -c /usr/local/etc/bacula-sd.conf root\ 63418\ 0.0\ 0.3\ 1856 1036\ ??\ Ss\ 4:09PM 0:00.00 /usr/local/sbin/bacula-fd -v -c /usr/local/etc/bacula-fd.conf root\ 63422\ 0.0\ 0.4\ 2360 1440\ ??\ Ss\ 4:09PM 0:00.00 /usr/local/sbin/bacula-dir -v -c /usr/local/etc/bacula-dir.conf
If you have a firewall or a DMZ installed on your computer, you may experience difficulties contacting one or more of the Clients to back them up. This is especially true if you are trying to backup a Client across the Internet.
If you are attempting to do this, the sequence of network events in Bacula to do a backup are the following:
Console -> DIR:9101 DIR -> SD:9103 DIR -> FD:9102 FD -> SD:9103
Where it should be obvious that DIR represents the Director, FD the File daemon or client, and SD the Storage daemon. The numbers that follow those names are the standard ports used by Bacula, and the -> represents the left side making a connection to the right side (i.e. the right side is the "server" or is listening on the specified port), and the left side is the "client" who initiates the conversation.
Note, port 9103 serves both the Director and the File daemon, each having its own independent connection.
If you are running iptables, you might add something like:
-A FW-1-INPUT -m state --state NEW -m tcp -p tcp --dport 9101:9103 -j ACCEPT
on your server, and
-A FW-1-INPUT -m state --state NEW -m tcp -p tcp --dport 9102 -j ACCEPT
on your client. In both cases, I assume that the machine is allowed to initiate connections on any port. If not, you will need to allow outgoing connections on ports 9102 and 9103 on your server and 9103 on your client. Thanks to Raymond Norton for this tip.
Jesse Guardiani's solution for his network for this problem, in his own words, is:
My bacula server is on the 192.168.1.0/24 network at IP address 192.168.1.52. For the sake of discussion we will refer to this network as the 'internal' network because it connects to the internet through a NAT'd firewall. We will call the network on the public (internet) side of the NAT'd firewall the 'external' network. Also, for the sake of discussion we will call my bacula server:
server.int.mydomain.tld
when a fully qualified domain name is required, or simply:
server
if a hostname is adequate. We will call the various bacula daemons running on the server.int.mydomain.tld machine:
server-fd server-sd server-dir
In addition, I have two clients that I want to back up with Bacula. The first client is on the internal network. Its fully qualified domain name is:
private1.int.mydomain.tld
And its hostname is:
private1
This machine is a client and therefore runs just one bacula daemon:
private1-fd
The second client is on the external network. Its fully qualified domain name is:
public1.mydomain.tld
And its hostname is:
public1
This machine also runs just one bacula daemon:
public1-fd
Finally, I have a NAT firewall/gateway with two network interfaces. The first interface is on the internal network and serves as a gateway to the internet for all the machines attached to the internal network (For example, server.int.mydomain.tld and private1.int.mydomain.tld). The second interface is on the external (internet) network. The external interface has been assigned the name:
firewall.mydomain.tld
Remember:
*.int.mydomain.tld = internal network *.mydomain.tld = external network
server-sd manages a 4 tape AIT autoloader. All of my backups are written to server-sd. I have just *one* Device resource in my server-sd.conf file:
Device { Name = "autochanger1"; Media Type = AIT-1; Archive Device = /dev/nrsa1; Changer Device = /dev/ch0; Changer Command = "/usr/local/sbin/chio-bacula %c %o %S %a"; Label Media = yes; AutoChanger = yes; AutomaticMount = yes; # when device opened, read it AlwaysOpen = yes; Hardware End of Medium = No Fast Forward Space File = No BSF at EOM = yes }
(note, please see the Tape Testing chapter of this manual for important FreeBSD information.) However, I have *two* Storage resources in my server-dir.conf file:
Storage { Name = "autochanger1-int" # Storage device for backing up Address = server.int.mydomain.tld SDPort = 9103 Password = "mysecretpassword" Device = "autochanger1" Media Type = AIT-1 Autochanger = yes } Storage { Name = "autochanger1-ext" # Storage device for backing up Address = firewall.mydomain.tld SDPort = 9103 Password = "mysecretpassword" Device = "autochanger1" Media Type = AIT-1 Autochanger = yes }
Note that BOTH of the above server-dir.conf Storage resources use the same 'autochanger1' Device resource from server-sd.conf.
My backup jobs run consecutively, one after the other, so only one of the above Storage resources is being used by Bacula file daemons at any given time. I don't know if this would cause problems at a site that runs more than one backup in parallel to a single tape device.
In addition to the above, I have two Client resources defined in server-dir.conf:
Client { Name = private1-fd Address = private1.int.mydomain.tld FDPort = 9102 Catalog = MyCatalog Password = "mysecretpassword" # password for FileDaemon } Client { Name = public1-fd Address = public1.mydomain.tld FDPort = 9102 Catalog = MyCatalog Password = "mysecretpassword" # password for FileDaemon }
And finally, to tie it all together, I have two Job resources defined in server-dir.conf:
Job { Name = "Private1-Backup" Type = Backup Client = private1-fd FileSet = "Private1" Schedule = "WeeklyCycle" Storage = "autochanger1-int" Messages = Standard Pool = "Weekly" Write Bootstrap = "/var/db/bacula/Private1-Backup.bsr" Priority = 12 } Job { Name = "Public1-Backup" Type = Backup Client = public1-fd FileSet = "Public1" Schedule = "WeeklyCycle" Storage = "autochanger1-ext" Messages = Standard Pool = "Weekly" Write Bootstrap = "/var/db/bacula/Public1-Backup.bsr" Priority = 13 }
It is important to notice that because the 'Private1-Backup' Job is intended to back up a machine on the internal network it uses the 'autochanger1-int' Storage resource. On the other hand, the 'Public1-Backup' Job is intended to back up a machine on the external network, so it uses the 'autochanger1-ext' Storage resource.
I have left the Pool, Catalog, Messages, FileSet, Schedule, and Director resources out of the above server-dir.conf examples because they are not pertinent to the discussion.
If I want to run a backup of private1.int.mydomain.tld and store that backup using server-sd then my understanding of the order of events is this:
Alternatively, if I want to run a backup of public1.mydomain.tld and store that backup using server-sd then my understanding of the order of events is this:
In order for the above 'Public1-Backup' Job to succeed, firewall.mydomain.tld:9103 MUST be forwarded using the firewall's configuration software to server.int.mydomain.tld:9103. Some firewalls call this 'Server Publication'. Others may call it 'Port Forwarding'.
Also, if you have denial of service rate limiting in your firewall, this too can cause Bacula disconnects since Bacula can at times use very high access rates. To avoid this, you should implement default accept rules for the Bacula ports involved before the rate limiting rules.
Finally, if you have a Windows machine, it will most likely by default disallow connections to the Bacula Windows File daemon. See the Windows chapter of this manual for additional details.
Kern Sibbald 2008-01-31