Friday, June 29, 2012

BIND and network unreachable messages...

Sometimes you'll see messages like the following ones in your log file (messages are slightly obfuscated to protect innocent :)):
Jun 29 14:32:11 someserver named[1459]: error (network unreachable) resolving '': 2001:503:a83e::2:30#53
Jun 29 14:32:11 someserver named[1459]: error (network unreachable) resolving '': 2001:503:231d::2:30#53
What these messages say is that network that contains address 2001:503:231d::2:30 is unreachable. So, what's happening?

The problem is that all modern operating systems support IPv6 out of the box. The same is for growing number of software packages, among them is BIND too. So, operating system configures IPv6 address on interface and application thinks that IPv6 works and configures it. But, IPv6 doesn't work outside of the local network (there is no IPv6 capable router) so, IPv6 addresses, unless in local networks, are unreachable.

So, you might ask now: but everything otherwise works, why is this case special! Well, the problem is that some DNS servers, anywhere in hierarchy, support IPv6, but not all. And when our resolver gets IPv6 address in response, it defaults to it and ignores IPv4. It obviously can not reach it so it logs a message and then tries IPv4. Once again, note that this IPv6 address can pop up anywhere in hierarchy, it isn't necessary to be on the last DNS server. In this concrete case name server for doesn't support IPv6, but some name server for the top level com domain do support it!

To prevent those messages from appearing add option -4 to bind during startup. On CentOS (Fedora/RHEL) add or modify the line OPTIONS in /etc/sysconfig/named so that it includes option -4, i.e.

Thursday, June 28, 2012

Another internal error trying to access IPA Web UI

I just tried to access IPA's Web UI and I got 'Internal Server Error' dialog box:

Looking into log file (/var/log/httpd/error_log) I found the following entry that obviously was the reason dialog box appeared:
[Thu Jun 28 21:10:28 2012] [error] [client] gss_acquire_cred() failed: Unspecified GSS failure.  Minor code may provide more information (, No key table entry found for HTTP/ipa.example-domain.local.localdomain@EXAMPLE-DOMAIN.HR), referer: https://ipa.example-domain.local/ipa/ui/
It's immediately obvious that something is wrong with the name of IPA server and that somehow .localdomain was appended!? At first, I thought that the problem is in the Firefox and that the value of keys network.negotiate-auth.trusted-uris and network.negotiate-auth.delegation-uris have to end with a dot so that no domain is appended. But quick test showed that I was wrong, when I added dots there nothing worked any more. :)

So, I thought that there must be something on a server that causes that behavior. And then, I looked into /etc/resolv.conf and there it was:
search localdomain example-domain.local
So, this search statement cause localdomain to be appended to the IPA's FQDN. So, I removed that statement and tried again, but the error was still there. Then, it occured to me that Apache probably memorized the statement so I restarted it. And, lo and behold, everyting worked.

You might wonder from where came this search statement. Well, I play tricks with my network setup, and in this case DHCP was used to obtain list of DNS servers which later I manually changed into But, I forgot to remove search statement and so the error occurred. Playing games with network setup obviously bites sometimes... ;)

Installing Alfresco Community Edition on minimal CentOS...

In this post I'm going to describe how to install Alfresco Community Edition 4.0d starting with a minimal CentOS 6 installation. This will be a two part post after which I'm going to describe how to integrate Alfresco with FreeIPA for authentication and authorization purposes. The goal of the installation is to use as much as possible software available in CentOS. The reason for doing so is that update process is easier, i.e. you only have to do yum update instead of manually downloading and installing updated software.

Environment and Configuration Parameters

I assume that you have CentOS installation ready. If not, then install it, and if you need some info on how to do it, look at this post. Furthermore, I assume that Alfresco should reside within Intranet, i.e. local network. The reason is that there is no need for Alfresco to be accessible from the Internet and thus it doesn't have to be in DMZ. I'll assign IP address to this host. The FQDN of the host will be alfresco.example-domain.local. Now, if you have working DNS you should put this name into DNS, but it's not necessary, i.e. you can put it into /etc/hosts file of any host that will access Alfresco (including Alfresco itself) and that will do for now.

Alfresco needs a relational database. I'm going to use MySQL database. Furhtermore, I'll assume that this database is on the same host as Alfresco. This will allow me to restrict access to database. Unfortunately, standard JDBC driver for MySQL doesn't support access to database via Unix socket, so database has to be accessible via network stack. I'm going to restrict it to loopback interface.

Note that I started with the following state of disk usage:
# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             7,0G  944M  5,7G  15% /

Prerequisite software installation

As for the prerequsite software you have to install the following packages (all of them shipped with CentOS):
  • java-1.6.0-openjdk - unless you explicitly specify which java you want to be installed, gcc's version will be used and that one won't work with Alfresco.
  • tomcat6 - servlet container that will run Alfresco. It is mandatory to install this package. This, along with dependencies, will be 129M to download and will take about 382M disk space.
  • mysql-server - this is a package that holds server part of MySQL database.
  • mysql-connector-java - JDBC connector that will allow Alfresco to access MySQL database.
  • unzip - so that you can unpack Alfresco archive (which is distributed as a zip file)
So, install it using yum. This will download 168M which will expand into 503M. Afterwards, this is the state of disk usage:
# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             7,0G  1,6G  5,1G  24% /

Configure MySQL database

We also have to prepare MySQL database, i.e. you have to do the following steps:
  1. Configure database to use UTF-8 by default.
  2. Configure it to listen only on loopback interface.
  3. Start database and set root password.
  4. Create alfresco database.
  5. Create alfresco user and assign it a password.
  6. Configure system to start MySQL database during the boot process.
The first two steps are done by editing /etc/my.cnf file. Integrate the following lines with the already existing content (i.e. to existing sections add missing lines, if the section doesn't exist in my.cnf file add it along with all its lines):


character-set-server = utf8
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
Note that MySQL has to listen on loopback because JDBC doesn't allow connection via Unix socket, at least not without tweaks to Alfresco code itself.

Step 3 (i.e. set root password) is done by starting MySQL server and then setting password:
/etc/init.d/mysqld start
/usr/bin/mysqladmin -u root password 'new-password'
String 'new-password' replace with your password (and keep quotes, they prevent shell from interpreting any special character in password you might have!). You should be careful with this password as it is very critical peace of information!

Step 4 and 5 (create alfresco database and user) are done using mysql tool. So, first start this tool:
# mysql -u root -p
Enter password: <type here root password>
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.61 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

and now create database:
mysql> create database alfresco;
Query OK, 1 row affected (0.00 sec)
and grant alfresco user all permissions on the database:
mysql> grant all privileges on alfresco.* to alfresco@localhost identified by 'PASSWORD';
Query OK, 0 rows affected (0.00 sec)
The word PASSWORD should be replaced with a password. Again, this one is critical since all the data will be accessible if someone gets hold on that password. And, while you are at that, remove test database as it is not necessary and might even present security threat:
mysql> drop database test;
Query OK, 0 rows affected (0.00 sec)
That's it as far as mysql client is concerned. So, leave it using exit keyword.

Finally, we should configure system to start MySQL database on each boot. This is easily done with:
chkconfig mysqld on
OK, so much about database. One more thing before going to Alfresco installation. You have to configure tomcat so that it loads MySQL connector when starting, otherwise Alfresco won't be able to connect to database! To to that, open file /etc/tomcat6/ and search for line "shared.loader=". Add to that line string /usr/share/java/mysql-connector-java.jar, i.e. it shoud look now like this:
Save the file and exit and that's it. Now on to Alfresco itself.

Alfresco Installation

First, go to Alfresco download site and download Community edition, i.e. download file Then, unpack it (using unzip tool) into a temporary directory:
mkdir tmp
cd tmp
unzip ../
<unzip progress output>
You'll have now few new directories. From directory web-server/webapps move files alfresco.war and share.war into tomcat webapps directory, i.e. into /var/lib/tomcat6/webapps. From now on, I'm going to reference that directory as $WEBAPPS, to shorten a bit typing. Now, start wait a minute and then stop tomcat server. This is so that it unpacks alfresco and share war archives:
/etc/init.d/tomcat6 start
/etc/init.d/tomcat6 stop
In case you receive ERROR message trying to stop tomcat, wait a bit more and then try again. Namely, until tomcat finishes initialization you can not stop it.

Note also that tomcat writes its logs into /var/log/tomcat6. You should monitor that directory when starting tomcat. More specifically, watch catalina.out file. Furthermore, the tip, I remove all log files before starting tomcat again so that it doesn't clutter new log messages with the old ones. Of course, I'm doing that only during installation phase. Later, it is very good idea to keep the logs around!

Go now into directory  $WEBAPPS/alfresco/WEB-INF/classes. There, you'll see file Copy this file into and change permissions to a more restrictive values:
chmod 600
and open it in editor. In there do the following:
  1. Immediately at the beginning uncomment lines  dir.root and dir.keystore. Set dir.root to a directory where Alfresco will store data. I used /var/lib/alf_data (which of course, should be created manually!) but any value with enough storage will do. Also, change the owner of that directory to tomcat and restrict access permissions so that only user tomcat can enter into that directory (use permissions 700). dir.keystore should be set to $WEBAPPS/alfresco/WEB-INF/classes/alfresco/keystore.
  2. Uncomment lines db.username and db.password and set correct value for password (username is alfresco so that shouldn't be necessary to change). This password in plain text is the reason you had to change permissions of the file.
  3. Find MySQL section, and in particular lines there db.driver and db.url and uncomment them. Change the value of db.driver to com.mysql.jdbc.Driver.
Now, open file that is in the same directory as the previous file, i.e. $WEBAPPS/alfresco/WEB-INF/classes. Find there the following line:
And change it to:
This line specifies where Alfresco will do its logging. The obvious place is the same directory where tomcat places its logs. Do the same change in file $WEBAPPS/share/WEB-INF/classes/

Now, start tomcat again and try to open the following URL in a Web browser: After a bit of wait you should be presented with a guest Alfresco home page. You can then logout and login as admin (U: admin/P: admin). Note that if you can not connect, the reason is firewall on Alfresco server. Temporarily turn off the firewall with:
/etc/init.d/iptables stop
and then try again.

Don't forget to configure system so that tomcat is started after each reboot. Anyway, this is the first part of the installation. There are some more tweaks you should do that I'm going to describe in the following post. For the end of this post let me show the disk usage:
# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             7,0G  2,1G  4,6G  31% /

Snort with MySQL support on 64-bit CentOS 6...

In one of the previous posts I wrote about compiling Snort on 64-bit CentOS. The newest stable version of Snort now is and I'll use that version from now on. But, the old post is still valid for compiling that new one, so there is no need for another post.

But, there is a problem. If  you tried to build Snort package with MySQL support like this:
rpmbuild --rebuild --with mysql snort-
then you certainly got the following message:
<some unrelated configure script output>
checking for mysql...

  ERROR: unable to find mysqlclient library (libmysqlclient.*)
  checked in the following places

error: Bad exit status from /var/tmp/rpm-tmp.R2KI5J (%build)

RPM build errors:
    Bad exit status from /var/tmp/rpm-tmp.R2KI5J (%build)
Well, the problem is that on 64-bit CentOS (and RHEL derivatives, including Fedora) 64-bit libraries are in /lib64 and /usr/lib64 directories. The easiest way to circumvent that problem is to do the following.

First, install SRPMS file so that it is unpacked:
rpm -ivh snort-
Then, go to ~/rpmbuild/SPEC directory, and open file snort.spec in some text editor. Search for the following block:
   if [ "$1" = "mysql" ]; then
        ./configure $SNORT_BASE_CONFIG \
        --with-mysql \
        --without-postgresql \
        --without-oracle \
        --without-odbc \
        %{?EnableFlexresp} %{?EnableFlexresp2} \
It's somewhere around line 231. Modify it to include line         --with-mysql-libraries=/usr/lib64, i.e. it should now look like follows:
    if [ "$1" = "mysql" ]; then
        ./configure $SNORT_BASE_CONFIG \
        --with-mysql \
        --with-mysql-libraries=/usr/lib64 \
        --without-postgresql \
        --without-oracle \
        --without-odbc \
        %{?EnableFlexresp} %{?EnableFlexresp2} \
Save and close file. Then, start snort build using the following command:
rpmbuild -bb --with mysql snort-
And that should be it...

Tuesday, June 26, 2012

Installing FreeIPA on minimal CentOS installation..

This post is a continuation on a minimal CentOS6 installation. The goal is to install FreeIPA that will be used as authentication and authorization server for Zimbra and Alfresco.

Environment and parameters

Referring to a figure given in a post about minimal CentOS6 installation, IPA server will be placed within a local network. Actually, it should be placed within separate network along with other servers not accessible from the Internet. But because I have only DMZ and one LAN segment for workstations and to keep things simple, obviously the local network is the place to go. So, based on that, the following parameters will be used:
  • The IP address of FreeIPA server will be
  • FQDN name will be ipa.example-domain.local. Note the domain name of the local network!
  • Kerberos REALM will be EXAMPLE-DOMAIN.COM.
I'm also assuming that you already have working DNS server, with both forward and reverse queries working! If you don't, you should first configure DNS (and then configure reverse DNS, too) and then proceed with FreeIPA. Of course, the two can be hosted on the same host, but for my scenario, DNS is with mail server in DMZ as it is accessible from the Internet, while FreeIPA is on a separate host in local network.

Software installation

The first step is to install base OS as specified in the post about minimal CentOS6 installation. Note that some things, like IP address, host name and DNS server should be appropriately changed!

After the base OS installation is finished next step is to install necessary software. So, install ipa-server package using yum:
yum -y install ipa-server 
This will result in installation of hefty set of dependencies, somewhere around 190M to download which will take aproximatelly 572M after installation. Anyway, disk usage after IPA server installation looks something like this:
# df
Filesystem  1K-blocks      Used Available Use% Mounted on
/dev/sda1     7739864   1600788   5745912  22% /

Sever configuration

Now, start server configuration program. Here is the transcript of installation I did:
# ipa-server-install

The log file for this installation can be found in /var/log/ipaserver-install.log
This program will set up the IPA Server.

This includes:
  * Configure a stand-alone CA (dogtag) for certificate management
  * Configure the Network Time Daemon (ntpd)
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)

To accept the default shown in brackets, press the Enter key.

Enter the fully qualified domain name of the computer
on which you're setting up server software. Using the form

Server host name [ipa.example-domain.local]:

The domain name has been calculated based on the host name.

Please confirm the domain name [example-domain.local]:

The IPA Master Server will be configured with
Hostname:    ipa.example-domain.local
IP address:
Domain name: example-domain.local

The kerberos protocol requires a Realm name to be defined.
This is typically the domain name converted to uppercase.

Please provide a realm name [EXAMPLE-DOMAIN.LOCAL]: EXAMPLE-DOMAIN.COM
Certain directory server operations require an administrative user.
This user is referred to as the Directory Manager and has full access
to the Directory for system management tasks and will be added to the
instance of directory server created for IPA.
The password must be at least 8 characters long.

Directory Manager password: <enter password>
Password (confirm): <enter password>

The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.

IPA admin password: <enter password>
Password (confirm): <enter password>

The following operations may take some minutes to complete.
Please wait until the prompt is returned.

Configuring ntpd
  [1/4]: stopping ntpd
  [2/4]: writing configuration
  [3/4]: configuring ntpd to start on boot
  [4/4]: starting ntpd
done configuring ntpd.
Configuring directory server for the CA: Estimated time 30 seconds
  [1/3]: creating directory server user
  [2/3]: creating directory server instance
  [3/3]: restarting directory server
done configuring pkids.
Configuring certificate server: Estimated time 3 minutes 30 seconds
  [1/17]: creating certificate server user
  [2/17]: creating pki-ca instance
  [3/17]: configuring certificate server instance
  [4/17]: disabling nonces
  [5/17]: creating CA agent PKCS#12 file in /root
  [6/17]: creating RA agent certificate database
  [7/17]: importing CA chain to RA certificate database
  [8/17]: fixing RA database permissions
  [9/17]: setting up signing cert profile
  [10/17]: set up CRL publishing
  [11/17]: set certificate subject base
  [12/17]: configuring certificate server to start on boot
  [13/17]: restarting certificate server
  [14/17]: requesting RA certificate from CA
  [15/17]: issuing RA agent certificate
  [16/17]: adding RA agent as a trusted user
  [17/17]: Configure HTTP to proxy connections
done configuring pki-cad.
Configuring directory server: Estimated time 1 minute
  [1/35]: creating directory server user
  [2/35]: creating directory server instance
  [3/35]: adding default schema
  [4/35]: enabling memberof plugin
  [5/35]: enabling referential integrity plugin
  [6/35]: enabling winsync plugin
  [7/35]: configuring replication version plugin
  [8/35]: enabling IPA enrollment plugin
  [9/35]: enabling ldapi
  [10/35]: configuring uniqueness plugin
  [11/35]: configuring uuid plugin
  [12/35]: configuring modrdn plugin
  [13/35]: enabling entryUSN plugin
  [14/35]: configuring lockout plugin
  [15/35]: creating indices
  [16/35]: configuring ssl for ds instance
  [17/35]: configuring certmap.conf
  [18/35]: configure autobind for root
  [19/35]: configure new location for managed entries
  [20/35]: restarting directory server
  [21/35]: adding default layout
  [22/35]: adding delegation layout
  [23/35]: adding replication acis
  [24/35]: creating container for managed entries
  [25/35]: configuring user private groups
  [26/35]: configuring netgroups from hostgroups
  [27/35]: creating default Sudo bind user
  [28/35]: creating default Auto Member layout
  [29/35]: creating default HBAC rule allow_all
  [30/35]: initializing group membership
  [31/35]: adding master entry
  [32/35]: configuring Posix uid/gid generation
  [33/35]: enabling compatibility plugin
Restarting IPA to initialize updates before performing deletes:
  [1/2]: stopping directory server
  [2/2]: starting directory server
done configuring dirsrv.
  [34/35]: tuning directory server
  [35/35]: configuring directory to start on boot
done configuring dirsrv.
Configuring Kerberos KDC: Estimated time 30 seconds
  [1/14]: setting KDC account password
  [2/14]: adding sasl mappings to the directory
  [3/14]: adding kerberos entries to the DS
  [4/14]: adding default ACIs
  [5/14]: configuring KDC
  [6/14]: adding default keytypes
  [7/14]: adding default password policy
  [8/14]: creating a keytab for the directory
  [9/14]: creating a keytab for the machine
  [10/14]: exporting the kadmin keytab
  [11/14]: adding the password extension to the directory
  [12/14]: adding the kerberos master key to the directory
  [13/14]: starting the KDC
  [14/14]: configuring KDC to start on boot
done configuring krb5kdc.
Configuring ipa_kpasswd
  [1/2]: starting ipa_kpasswd
  [2/2]: configuring ipa_kpasswd to start on boot
done configuring ipa_kpasswd.
Configuring the web interface: Estimated time 1 minute
  [1/13]: disabling mod_ssl in httpd
  [2/13]: setting mod_nss port to 443
  [3/13]: setting mod_nss password file
  [4/13]: enabling mod_nss renegotiate
  [5/13]: adding URL rewriting rules
  [6/13]: configuring httpd
  [7/13]: setting up ssl
  [8/13]: setting up browser autoconfig
  [9/13]: publish CA cert
  [10/13]: creating a keytab for httpd
  [11/13]: configuring SELinux for httpd
  [12/13]: restarting httpd
  [13/13]: configuring httpd to start on boot
done configuring httpd.
Applying LDAP updates
Restarting IPA to initialize updates before performing deletes:
  [1/2]: stopping directory server
  [2/2]: starting directory server
done configuring dirsrv.
Restarting the directory server
Restarting the KDC
Restarting the web server
Sample zone file for bind has been created in /tmp/
Setup complete

Next steps:
    1. You must make sure these network ports are open:
        TCP Ports:
          * 80, 443: HTTP/HTTPS
          * 389, 636: LDAP/LDAPS
          * 88, 464: kerberos
        UDP Ports:
          * 88, 464: kerberos
          * 123: ntp

    2. You can now obtain a kerberos ticket using the command: 'kinit admin'
       This ticket will allow you to use the IPA tools (e.g., ipa user-add)
       and the web user interface.

Be sure to back up the CA certificate stored in /root/cacert.p12
This file is required to create replicas. The password for this
file is the Directory Manager password
As you can see the process is quite automated.

Postinstallation steps

There are few more things that have to be done before clients can be configured. Note the italic text almost at the end of the transcript? It says that there is a file with data you should place in your DNS server. The file is only example, and basically it defines the whole zone. But since we already have working zone, we only need the IPA related part, i.e. without SOA, NS and A records. That would be the following fragment:
; ldap servers
_ldap._tcp              IN SRV 0 100 389        ipa

;kerberos realm
_kerberos               IN TXT EXAMPLE-DOMAIN.TXT

; kerberos servers
_kerberos._tcp          IN SRV 0 100 88         ipa
_kerberos._udp          IN SRV 0 100 88         ipa
_kerberos-master._tcp   IN SRV 0 100 88         ipa
_kerberos-master._udp   IN SRV 0 100 88         ipa
_kpasswd._tcp           IN SRV 0 100 464        ipa
_kpasswd._udp           IN SRV 0 100 464        ipa

;ntp server
_ntp._udp               IN SRV 0 100 123        ipa
Basically, these records define services provided by IPA so that they are discoverable by DNS. All the services (or server - SRV - records) consist of two parts, the first one defines service name with prepended underscore while the second part defines transport protocol, also with prepended underscore. So, for example, there is LDAP over TCP protocol (_ldap._tcp) which listens on port 389 (standard LDAP port) on IPA host. Anyway, place those lines in example-domain.local, and in internal view of zone files. Don't forget to change serial number of zone file and to restart BIND after the change.

It's time to test that IPA is working correctly. First, request ticket for user admin:
# kinit admin
Password for admin@EXAMPLE-DOMAIN.COM:
You are asked password that you entered during installation process! Anyway, you shouldn't receive any message and that means you were issued ticket. To check ticket, use klist command:
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE-DOMAIN.COM

Valid starting     Expires            Service principal
06/26/12 17:43:05  06/27/12 17:43:01  krbtgt/EXAMPLE-DOMAIN.COM@EXAMPLE-DOMAIN.COM
If you got output as shown (or similar) then IPA is working correctly. Note that when you have to do something with IPA (using command line tool ipa) you are authorized (and authenticated) with the ticket. So, for example, when you are adding new user, you need to have valid admin ticket.

Client installation

Finally, we'll describe setup of a client, more specifically, Firefox browser. This is necessary so that you can use Web interface to administer IPA server. Two things have to be done. First, you have to edit /etc/krb5.conf file. The content of that file should look like this:

        default = FILE:/var/log/krb5libs.log
        kdc = FILE:/var/log/krb5kdc.log
        admin_server = FILE:/var/log/kadmind.log
        default_realm = EXAMPLE-DOMAIN.COM
        dns_lookup_realm = false
        dns_lookup_kdc = false
        ticket_lifetime = 24h
        renew_lifetime = 7d
        forwardable = true
                kdc = ipa.example-domain.local
                admin_server = ipa.example-domain.local
        .example-domain.local = EXAMPLE-DOMAIN.COM
        example-domain.local = EXAMPLE-DOMAIN.COM
Basically, in this file you define default realm (so that you can write kinit admin, instead of full kinit admin@EXAMPLE-DOMAIN.COM), and you also define KDC server for this real (under realm section). Finally, you define mapping from domain names to realm. In our case, we have a single realm that is valid in all domains. Note that it is possible to use DNS to resolve much of the information we gave in the configuration file but I'm not using that feature currently (dns_lookup_* = false). There is one more reason I'm not using DNS resolution. Namely, while my IPA and DNS servers are virtual machines, I'm using my physical laptop as a client and I don't want to change DNS server for laptop or otherwise half of the things would stop working. :) Oh, yeah, if you are doing the same, don't forget to put name ipa.example-domain.local into /etc/hosts on a laptop. Otherwise, you'll get the following error message:

$ kinit admin
kinit: Cannot contact any KDC for realm 'EXAMPLE-DOMAIN.COM' while getting initial credentials
This actually means that the KDC host name isn't resolvable. If you get the following error message:

$ kinit admin
Password for admin@EXAMPLE-DOMAIN.COM:
kinit: Clock skew too great while getting initial credentials
That means that the clock on one of the machines (KDC or your laptop, or both) is wrong and the difference is too large. So, check and fix clocks. Finally, when everything is OK, you should get no error messages:

$ kinit admin
Password for admin@EXAMPLE-DOMAIN.COM: 
And you can use klist to very that you really got ticket. This ticket is important because without it Web application won't let you access it. Ok, now Firefox configuration. This is done via Firefox browsing, so it's easy. :)

Open Firefox and type IPA server's IP address (or name) into URL location. The first thing you are asked is to import untrasted certificate because you are switched to HTTPS connection. When you've done that you'll receive dialog box that informs you that you have to import CA from IPA server. During the import process it is very important to select all check boxes! Otherwise, the next step won't work! Ok, the next step is automatic configuration of Firefox configuration to allow kerberos ticket forwarding to remote host. When it's done reload page and you should have access to adminstration interface.

I had a problem with some internal error by Web application. It turned out that my laptop used IP address that Web application couldn't resolve to name (via reverse DNS), and then to realm. I had to enter laptop name and IP address into DNS server. Also, be careful that you use the correct DNS server on IPA server.

So, that's it for this post. :)

Setting up reverse DNS server...

In the post about DNS configuration I skipped reverse DNS configuration. But, it is necessary to have it in some cases, like FreeIPA installation or for mail servers. So, I'm going to explain how to configure reverse DNS server.

While "normal" DNS resolution works by names, from root server down to the authoritative one for the name we are looking for, reverse DNS resolution works within special top-level domain ( Within this domain, sub-domains are comprised from octets within IP address in reverse order. Now, if your block of IP addresses ends on byte boundary (e.g. /8, /16, /24) the setup is relatively simple. Otherwise, you upstream provider (the one that holds larger IP address block) has to point to your domain on a per address base.

Let us bring this to more concrete values. Suppose that our public IP address space is Also, suppose that your mail server has public IP address In that case, reverse query is sent for name and query type is set to PTR, i.e. we are looking for a name 2 within zone.

So, it's relatively easy to setup reverse DNS. You need to define appropriate zones that include only network part of your IP addresses. In our case we have two zones, but IP addresses used for one of them depends on who's asking (client from the local network or client on the Internet). So, we have three zones in effect:
  1. DMZ, when asked by local clients, is in the network This means we have reverse zone for local clients.
  2. DMZ, when asked by internet clients, is in the network This means that for them reverse zone is
  3. Finally, clients in local network (non-DMZ one) have IP addresses from a block and so they are placed within reverse zone
So, within internal view you should add the following two zone statements:
zone "" {
    type master;
    file "";

zone "" {
    type master;
    file "example-domain.local.rev";
And within internet view you should add the following zone statement:
zone "" {
   type master;
    file "";
Then, you should create the three zone files (, example-domain.local.rev, and with the following content:
# cat
 $TTL 1D
@    IN    SOA    @ (
            2012062601 ; serial
            1D         ; refresh
            1H         ; retry
            1W         ; expire
            3H )       ; minimum

1          PTR
# cat example-domain.local.rev
 $TTL 1D
@    IN    SOA    @ (
            2012062601 ; serial
            1D         ; refresh
            1H         ; retry
            1W         ; expire
            3H )       ; minimum

1          PTR    test.example-domain.local.
# cat
@    IN    SOA    @ (
            2012062601 ; serial
            1D         ; refresh
            1H         ; retry
            1W         ; expire
            3H )    ; minimum

1          PTR
Don't forget to change permissions on those files as explained in the previous post. Now, restart BIND and test server:
# nslookup

[root@ipa ~]# nslookup
Address:    name =
As it can be seen, DNS server correctly handles request for IP addres and returns Let's try with a name from LAN:
# nslookup test.example-domain.local

Name:    ipa.example-domain.local

[root@ipa named]# nslookup
Address:    name = test.example-domain.local
That one is correct too. So, that's it, you have reverse DNS correctly configured. Testing from the outside I'm leaving to you as an exercise. ;)

Monday, June 25, 2012

Setting up DNS server...

In the previous post I described how to install minimal CentOS distribution with some additional useful tools. In this part I'm going to describe how to install DNS server. This DNS server will exhibit certain behavior depending on where the client is, in other words we are going to setup split DNS. Note that since DNS server is accessible from the Internet, it is placed in DMZ network, i.e.

Environment and configuration parameters

In the following text we assume network topology from the previous post, but we need some additional assumptions and requirements before going further. First, our public domain is and all hosts within DMZ will belong to that zone, i.e. FQDN of mail server will be But, when some client from the Internet asks for certain host, e.g. DNS server will return public IP address. On the other hand, when client from a local network, or even DMZ, asks for the same host private IP address will be returned, i.e. The reason for such behavior is more efficient routing. In other words, if client from a local network would receive public IP address, then all the traffic would have to be NAT-ed. We'll also assume that we are assigned a public block of IP addresses

There will be  also additional domain example-domain.local in which all the hosts from the local domain will be placed. Additionally, this domain will be visible only from the local network and DMZ, it will not exist for clients on the Internet.

To simplify things we are not going to install secondary DNS server nor we are going to install reverse zones. For a test purposes this is OK, but if you are doing anything serious, you should definitely install slave DNS servers (or use someone's service) and configure reverse zones. Also, I completely skipped IPv6 configuration and DNSSEC configuration.

Installation of necessary packages

There are a number of DNS server implementations to choose from. The one shipped with CentOS is BIND. It is the most popular DNS server, with most features, but, in the past it had a lot of vulnerabilities. Nevertheless, we'll use that one. Maybe sometime in future, I write something about alternatives, too.

So, the first step, is to install necessary packages:
yum install bind.x86_64 bind-chroot.x86_64 bind-utils.x86_64
Server itself is in bind package, bind-chroot is used to confine server to alternative root filesystem in case it is compromised. Finally, bind-utils contains utilities we need to test server. This is 4.1M of download data, and it takes around 7M after installation. Not much.

Note that it is a good security practice to confine server into alternative root. As I already said, in the past bind had many vulnerabilities, and in case new one is discovered and exploited, we want to minimize potential damage.

That's all about installation.


Next, we need to configure server before starting it. Main configuration file for bind is /etc/named.conf . So, open it with your favorite editor as we are going to make some changes in it. Remember that our domain is called and that we want private addresses to be returned for internal clients, and public ones for external clients. Additionally, we have a local domain example-domain.local. Here is the content of the /etc/named.conf file:
acl lnets {;;;

options {
  listen-on port 53 { any; };
  directory     "/var/named";
  dump-file     "/var/named/data/cache_dump.db";
  statistics-file "/var/named/data/named_stats.txt";
  memstatistics-file "/var/named/data/named_mem_stats.txt";
  allow-update     { none; };
  recursion no;

  dnssec-enable no;

view "internal" {
    match-clients { lnets; };
    recursion yes;

    zone "." IN {
        type hint;
        file "";

    zone "example-domain.local" {
        type master;
        file "example-domain.local";

    zone "" {
        type master;
        file "example.domain.local";

    include "/etc/named.rfc1912.zones";

view "internet" {
    match-clients { any; };
    recursion no;

    zone "" {
        type master;
        file "";
Let me now explain what this configuration file actually specifies. In global, there are four blocks, i.e. acl, options, and two view blocks.

acl block (or blocks, because there may be more such statements) specifies some symbolic name that will refer to group of addresses.  This is good from maintenance perspective because there is only one place where something is defined. In our case, we define our local networks, i.e. DMZ and local LAN. There is also loopback address because when some application on DNS server itself asks something, DNS server should treat it as if it is coming from a local network.

Next is an option block. In our case we specify that DNS server should listen (listen-on) port 53 on any IP address (any). In case you want to restrict on which addresses DNS server listens, you can enumerate them here instead of any keyword. Better yet, create ACL and use symbolic name. In option block we also disabled DNSSEC (dnssec-enable no), disabled updates to server (allow-update no), and disabled recursion (recursion no). Apart from that we defined directories, e.g. for zone files.

Finally, there are two view statements. They define zones depending on where the client asking is. If it is on the local networks, then first view (i.e. internal) is consulted, and if the client is anywhere else, then the second view is consulted (i.e. internet). match-clients statement classifies clients, and it is here that we use our ACL lnets. When query arrives, the source address from the packet is taken and compared to match-clients. The first one that matches is used. So, it is obvious that the second view matches anything but since it is the last one, then it is a catch-all view. Anyway, for our local clients we allow recursive queries (recursion yes), while we disallow it for a global clients (recursion no). This is a good security practice! Also, note that for internal clients we define example-domain.local zone, which isn't defined for global clients. And, for the same zone, two different files (i.e. databases with names) are used. This reflects the fact that we want local clients to get local IP addresses, while global clients should get globally valid IP addresses.

Zone configurations

There are three zones in our case. First one is a global one, used to answer queries to clients on the Internet. Looking into the main configuration file the name of the file containing this zone has to be and it has to be placed in /var/named directory! The content of this file is:
@    IN    SOA    @ (
            2012062501    ; serial
            1D            ; refresh
            1H            ; retry
            1W            ; expire
            3H )          ; minimum

ns1        A
There are three records in the file. The first one defines zone itself, it is called Start of Authority, or SOA. The @ sign is shorthand for zone name and it is taken from the /etc/named.conf file. Then, there is a continuation that defines name server (NS) for the zone. It is continuation because the first column (where @ sign is) isn't defined so it is taken from the previous record. Name server is Finally, there is IP address of the name server (A record). You should keep in mind that any name that doesn't end with dot is appended with a domain name. A lot of errors are caused by that omission. For example, if you wrote (without ending dot) this would translate into which is obviously wrong. But note that we are counting on this behavior in A records since we only wrote a name, without a domain!

The other zone files are similar to the previous one and also have to be within /var/named directory. I.e. for local view of the content of zone file is:
@    IN    SOA    @ (
            2012062501 ; serial
            1D         ; refresh
            1H         ; retry
            1W         ; expire
            3H )       ; minimum

ns1        A
Note that it is almost identical, except that IP address for name server is now from a private range! Finally, here is the content of zone that contains names from a local network:
@    IN    SOA    @ root.example-domain.local. (
            2012062501 ; serial
            1D         ; refresh
            1H         ; retry
            1W         ; expire
            3H )       ; minimum

test        A
Again, almost the same. Note that I added one test record with phony IP address. This is so that I can test DNS server if it is correctly resolving IP addresses.

One final thing before starting DNS server! You should change file ownership and SELinux context. To do so, use the following two commands (run them in /var/named directory):
chcon system_u:object_r:named_zone_t:s0 example-domain.*
chown root.named example-domain.*
The first command changes SELinux context, and the second one owner and group of files. So, it is time to start BIND, i.e. DNS, server:
/etc/init.d/named start
If there were some error messages, like the following one:
zone loading from master file failed: permission denied
zone not loaded due to errors.
Then something is wrong. Look carefully what it says to you as the error messages are quite self explanatory! In this particular case the problem is that DNS server can not read zone file. If you get that particular error message, check that SELinux context and ownership were changed properly.


Now, if you get just OK, it doesn't yet mean that everything is OK. You have to query server in order to see if it responds correctly. But, if there were any errors, they will be logged in /var/log/messages.

To test DNS server, use nslookup like this:
nslookup <name>
Here, I assume you are testing on a DNS server itself. If you are testing on some other host then you should change address with proper IP address of DNS server (public one in case you ask from the internet, local one if you are asking from some computer in DMZ or local network). In any case you should receive correct answers. Here are few examples:
# nslookup

# nslookup test.example-domain.local

Name:    test.example-domain.local
As expected, when internal host sends request internal IP address are returned. You should also check that any valid name is properly resolved (recursive queries). For example, you could ask for
# nslookup

Non-authoritative answer:    canonical name =
Which, in this case, resolves properly.

Now, there is a question how to test if names are properly resolved for clients on the Internet. The obvious solution is to try from some host on the Internet and see what's happening. In case you don't have host on the Internet, you can cheat using NAT. ;)

Do the following. First, add some random IP address to your loopback interface, i.e.:
ip addr add dev lo
Then, configure NAT so that any query sent via loopback gets source IP address changed:
iptables -A POSTROUTING -o lo -t nat -p udp --dport 53 -j SNAT --to-source
And now, try to send few queries:
# nslookup

** server can't find REFUSED
That one is OK. Namely, we don't want to resolve third party names for outside clients (remember, recursive is off!). Next test:
# nslookup ns1.example-domain.local.

** server can't find ns1.example-domain.local: REFUSED
This one doesn't work either. Which is what we wanted, i.e. our local domain isn't visible to the outside world. Finally, this one:
# nslookup

Which sends us correct outside address.

So, all set and done. Don't forget to remove temporary records (i.e. test), iptables rule, lo address, and also don't forget to modify /etc/resolv.conf so that your new server is used by default by local applications.

Sunday, June 24, 2012

Radno vrijeme ambulante u sklopu Cvjetnog naselja...

Fascinantno je kako je u stvari teško doći do podataka o radnom vremenu te ambulante! Već po N-ti puta guglam na sve strane ne bi li našao kojim datumima ambulanta radi prijepodne, a kojima poslijepodne i svaki puta potrošim po barem sat vremena za to. Konačno, uspio sam naći na ovom linku taj podatak, a kako idući puta opet ne bi trošio vrijeme bez veze, odlučio sam na blogu zapisati radno vrijeme. Dakle, parnim datumima radi od 13:00 do 20:30, a neparnima od 07:00 do 14:30. Dodatno, petkom ambulanta uvijek radi prijepodne. Pauza je od 10 do 10:30 te od 16 do 16:30. I da, pacijenti se primaju pola sata po početku radnog vremena do pola sata prije kraja radnog vremena. Konačno, broj telefona ambulante je 6191 231.

Tako, da idući put ne gubim vrijeme bez veze!

Napomena: doktorica i sestra su na godišnjem od 15.7.2016. do 15.8.2016. Zamjene su:

  • Od 18.07. do 29.07. zamjena je Dr. H. Šimurina (Horvaćanska cesta 35, ispod restorana Brazil) koji neparne datume radi ujutro, a parne poslije podne. Telefon je 01/3010972.
  • Od 01.08. do 12.08. zamjena je Dr. R. Marković Kunić (Jarunska bb, studom S. Radić) koja neparne datume radi poslije ponde, a parne ujutro. Telefon je 01/3028455

Napomena: od 21.3.2016. do 4.4.2016. ambulanta neće raditi zbog godišnjeg odmora. Definirano je kamo trebaju ići oni koji trebaju liječnika, ali znam samo da je negdje kod studentskog doma Sava.

Napomena: od 12.2.2016 ambulanta je vraćena na staru lokaciju u sklopu studentskog doma te radi po uobičajnom režimu (petkom uvijek prijepodne!).

Napomena: od 1.8.2015. pa na dalje ambulanta je privremeno preseljena u Dom zdravlja - studentski dom Cvjetno naselje, Odranska ul. 8, Zagreb. To je odmah pored samog doma Cvjetno naselje. I dalje radi parnim datumima poslijepodne te neparnim prijepodne, no tako je i petkom, tj. petkom NE radi samo prijepodne. Razlog preseljenja je obnova studentskih domova.

Tuesday, June 19, 2012

VMWare Workstation on Fedora 17...

Today, when I started VMWare Workstation, it notified me that there is a free security update. Since it is advisable to update whenever there are security issues, I approved it, but of course that after update I had a problem starting VMWare workstation. Since there are constantly problems with VMWare and Fedora I finally decided to track everything I had to do in this post. In other words, this post will be updated whenever I have to do something to VMWare Workstation to get it to work.

Ok, as I said, on a fully updated Fedora 17 (kernel-3.4.2-4.fc17.x86_64) when a new VMWare Workstation 8.0.4 is installed (or updated) it can not configure itself because of errors in kernel modules. As I wrote this I wasn't able to find a patch that fixes everything in one step, but I managed to combine two fixes that allowed VMWare to start. First, I had to apply patch for 8.0.3 that fixed vmnet.tar file. To do that I also had to modify a bit the script distributed with patch so that it accepts the fact that I'm using a newer version of VMWare (i.e. 8.0.4 instead of 8.0.3). Then, I had to apply a small fix for vmblock.tar that I wrote about in other post. Finally, I tried to start VMWare Workstation but it failed again?! After a bit poking, I realized  that there were dangling processes/modules so I had to kill all VMWare processes, remove modules, and that start succeeded. Of course that I could also restart the laptop, but because of the number of open windows I have, that wasn't an option. :)

When I did all that, then I found out that there is a patch that does all this, i.e. those two steps but combined, but it is for VMWare Workstation 8.0.2, which means you still have to poke a bit in script that applies a patch. And finally, this blog seems to be a good place to look when you have some problems with VMWare (and VirtualBox) and newer versions of kernel.

Thursday, June 14, 2012

An interesting article about car dealers...

Yesterday I lost over an hour reading the article titled Confessions of a Car salesman. Very interesting peace, worth of reading, and probably valid for other situations and other countries, like Croatia, too. Thinking a bit more about this, I'm certain that everything in life is in essence a process of buying and selling. Probably someone more experienced/knowledgeable that I am will laugh now as I discovered hot water. :) But hey, it's better to realize that sooner than later. :)

So, I'll emphasize few things I found interesting in the paper and that I remembered:
  • The first one is "up to" method. When you want to sell something, you ask how much the one buying is prepared to give. When you hear the price, you then ask 'Up to...?' and that buyer then increases a price by himself. :)
  • Also, what was interesting is that when you enter office, the probability that you'll buy something rises. This is one of the tactics of sellers, get a person into the office. What's interesting is that this reminded me when I was in Egypt. Tactics there is to get you into the shop and to do that they use different tricks, e.g. they have a present for you, but nothing to put it into so you'll have to come with him into his shop.
  • When you are trying to sell something, you have to talk constantly. It is not so important what you are talking about as it is not to stop talking. :) This reminds me of cases where I overheard some guy seducing a woman and thinking what a stupid things he's saying. But, the point was not to stop talking. :)
  • Buying over the Internet removes a lot of pressure from buyer, so it is advisable to use the Internet, at least as a preparation for buying something.
  • It's good to work in pairs. Namely, in that case one can be bad, in a sense that he/she brings bad news, so that you can be good guy and to have confidence from a buyer while in the same time claiming that bad guy said something and you can not negotiate it.
  • When approaching someone it's good to start with small talk just to relax that one you approached.
But only later I realized that this article was written in 2001. and I was really surprised. So I wonder, what, if anything, changed from that time. Probably one thing changed, namely, in the article it says that Internet is "ruining" a bussines, and it's certainly true that Internet today is more popular than it was 10 years ego. Nevertheless, it's good one. Some time in a future I intend also to read other Confession articles, too.

Sunday, June 10, 2012

Stuxnet... the origin... and implications...

Wow! I was reading Jeffrey Carr's post in which he admits being wrong about Stuxnet origin, and he references this article that made him change is minde. It is definitely a fascinating read about Stuxnet, how it was conceived, developed and used. I recommend that you take a time and read it! Namely, for several years now you'll find all over the Internet accusations that Chinese government is attacking western companies and governments. But this shows that other governments aren't sitting and doing nothing. Moreover, this article shows that malware has been brought to a new level of use in which it is used as attack weapon, to cite the article: Somebody crossed the Rubicon.

I suppose this will have a huge impact and lot of implications:
  1. Russia is pushing towards some kind of international treaty that would regulate use of cyberweapons. One of the advocates of this is Kaspersky, but there are also critiques. Anyway, this article gives a push to Russian government intentions.
  2. What impact will this have to closed source software? Because, no one can never be sure what's in there, especially if the company producing this software is under control of foreign country. Now, Microsoft already gave access to source code of, I think India among others, but this also means that Indian secret services can find bugs and use it against other countries? Sounds like Games without frontiers...
  3. Antivirus software, NIDS, HIDS and usual protection doesn't help here! They relay on a mass, i.e. someone gets infected but this allows anti virus companies to analyze threat, to create signatures and to update anti virues software so that huge majority is protected. These are, in a way, custom made attack programs.
  4. With a backup of government agencies, these attacks can be very sophisticated. But note that anyone with enough resources (i.e. reach enough) can do the same.
All in all, very interesting and far reaching developments...

Wednesday, June 6, 2012

Fedora 17, XeLaTeX and Beamer...

I decided to write this post about XeLaTeX and my attempts to process one presentation written using Beamer class into PDF file. The reason is that I certainly lost few hours trying to resolve the set of errors, and maybe someone finds this information/experience helpful.

The first problem I had after starting xelatex was the following error:
! Package pgfsys Error: Driver file ``pgfsys-xetex.def'' not found..

See the pgfsys package documentation for explanation.
Type  H   for immediate help.
l.847 ...ver file ``\pgfsysdriver'' not found.}{}}
? X
No pages of output.
So, I tried to find out which package provides this file using yum. But, no luck there. Then, I continued with google-fu. I found many links, but nothing that could be applied to my case, until I stumbled on this solution which basically tells me to copy one existing pgfsys file into the missing file, without any changes. What this post doesn't tell you explicitely is that you have to run texhash after that so that tex's file database is rebuilt.

When I again started xelatex, this time it seemed as if it will work! It was processing files and constantly giving some output. But no! At one point it stopped and I got the following error:
! Font \zf@basefont="TeX Gyre Cursor" at 10.0pt not loadable: Metric (TFM) file
 or installed font not found.
\zf@fontspec ...ntname \zf@suffix " at \f@size pt
                                                  \unless \ifzf@icu \zf@set@...
l.80 ...d,NoCommon,NoContextual}]{TeX Gyre Cursor}
Back to google-fu! Still, for this one it was easier to identify what's the problem. Namely, the font is missing (Metric (TFM) file or installed font not found). Again, using yum I found out that this font isn't packaged with Fedora 17 but it can be obtained from here. I downloaded zip archive, unpacked it, and moved all the font files into /usr/share/fonts/otf directory (before that I created otf subdirectory as it didn't exist). Afterwards, everything worked and presentation was successfully created. Note that I initially tried to place those fonts into /usr/share/texmf/fonts/opentype/public/tex-gyre/ directory. But that didn't work for unknown reason!

And guess what?! Now the source tex file was successfully transformed into PDF file.

While googling to find out solutions to problems I had, I realized that TeXLive distribution in Fedora 17 is 2007, while the newest version is 2011 with 2012 in development. Furthermore, I found out that  there is a plan for Fedora 18 to update TeXLive to at least version 2012. Since beta (or alpha) packages are readily available for F17, and I felt bold enough, I decided to give it a try.  So I installed repository per instructions on a given page and run 'yum update', and after a long wait, I tried again to run xelatex on the beamer presentation. This time I was completely out of luck:
kpathsea: Running mktexfmt xelatex.fmt
I can't find the format file `xelatex.fmt'!
For some reason, there was no xelatex.fmt file. As usual, first thing was to run 'yum whatprovides' to find out which package provides that file. But, none does! It seems to be a 'bug' in packages, so I had to revert texlive distribution. This was also a kind of a trial and error process, but to cut the story short what I did was: disabled texlive repository with experimental packages. Then, I used rpm to force removal of existing texlive packages, and then using yum I reinstalled the old ones (note that yum downgrade didn't work!). Finally, I used 'yum check/install' to fix any unresolved dependencies.

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)

Blog Archive