JWhoisServer :: Java Whois Server

Installation Guide

© 2007 - 2014 Klaus Zerwes zero-sys.net
This HowTo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY!
This document refers to JWhoisServer 0.4.1.2
The newest version of this document may be found at the sourceforge homepage of jwhoisserver
JWhoisServer is hosted on sourceforge All files and documentations may be downloaded from there.
SourceForge.net Logo.

Table of contents:
jump to the table of contents
About JWhoisServer
JWhoisServer is a small, fast and highly configurable RFC 3912 compliant whois server written in java and using a RDBMS as a storage engine.

Features:
jump to the table of contents
License of JWhoisServer
JWhoisServer is available under the following licenses:
  1. Licensed under the terms of the GNU Affero General Public License (AGPL), version 3 or later, as published by the Free Software Foundation.
    AGPL Logo
    This License applies to all public available releases. See LICENSE.txt for more details.
  2. In order to meet the requirements of all registrars, JWhoisServer additionally is available under a commercial license. For details please contact me using: http://www.zero-sys.net/portal/Kontakt.html
jump to the table of contents
Preface
Explanations of the syntax conventions used in this document:
jump to the table of contents
Important Release Notes
Release-Notes for Version 0.4.1.2:
  • IMPLEMENTED: server.velocity.context config property
Release-Notes for Version 0.4.1.0:
  • Support for CUBRID implemented.
  • A first (beta) installer for Microsoft Windows is available.
  • The dynamic JDBC driver loader was fixed/improved.
  • A dynamic plugin system for DBServerType has been implemented.
Release-Notes for Version 0.4.0.0:
  • Loading of multiple configuration files via the commandline has been implemented.
  • Implemented the dynamic DBServerType loading from cfg files. This way new database types may be added without the need to recompile the code.
    Configuration properties:
    • server.dbtypes.dir default: /etc/jwhoisserver/dbtypes/
    • server.dbtypes.glob default: .cfg
    This obsoletes the following configuration properties (see file deprecated.properties):
    • db.protocol
    • db.properties
    • db.jdbcclass
  • Implemented the dynamic loading of JDBC drivers from a configurable directory without the need to change the CLASSPATH in the starter scripts and the Manifest file.
    server.jdbc.dir default: /etc/jwhoisserver/jdbcdrivers/
  • Implemented the dynamic loading of plugins for DisplayObject from a configurable directory without the need to recompile the code.
    server.plugins.dir default: /etc/jwhoisserver/plugins/
  • db.ignoreemptyfields as a global setting and on a per display-object base may be used to suppress empty fileds in the output.
  • support for H2 Database Engine
  • JWhoisServer goes Debian (thx to Adrian von Bidder)!
    For this the debain packaging has been changed and support for postgreSQL via dbconfig-common has been added.
Release-Notes for Version 0.3.3.0:
Implemented the autodetection of the request type using the regex from DisplayObjects. For this db.objectlookupdefault may now contain a list of DisplayObjects. If the server recieves a unspecified request (without -T), we will loop all DisplayObjects from the list and will use the first where the request string matches the configured regex. Therefore only the last element from the list may have a empty regex (as this will always match).
Release-Notes for Version 0.3.2.0:
New features available in this release:
  • IDN support (see below)
  • multiple qfields for a lookup may be configured:
    • db.$DISPLAYOBJECT.qfield may be configured for multiple fields using db.listseparator or a separator defined using db.$DISPLAYOBJECT.qfieldseparator.
      db.$DISPLAYOBJECT.qfieldoperator may be used to define the logical operator for the combination of the qfields in the WHERE-clause (defaults to AND)
      Example: db.domain.qfield=domainidn;domainace will expand to the WHERE-clause domainidn = ? OR domainace = ? This way a lookup for a domain may be matched against 2 or more fields / collums in the DB.
  • db.DISPLAYOBJECT.transformquery has been implemented. Using this feature, the request string for a lookup may be transformed befor passing it to the database.
    Recognized values;
    • 0 empty do nothing
    • 1 lower lowercase tolower tolowercase uncapitalize uncapitalized to lower case
    • 2 upper uppercase toupper touppercase capitalize capitalized to upper case
    • 4 idn2ace ace toascii to ACE ASCII (requires java min 1.6)
    • 8 ace2idn idn tounicode to IDN Unicode (requires java min 1.6)
    In order to combine multiple transformations you can use:
    1. A list of values separated by listseparator. The order will be like in the list.
      Examples:
      db.domain.transformquery=lower;tounicode db.domain.transformquery=1;8
    2. The sum of the numeric values. The order will be in ascending numerical order
      (requires java min 1.6; see: descendingKeySet in TreeMap)
      Examples:
      db.domain.transformquery=9
      will evaluate to the same as
      db.domain.transformquery=tounicode;lower
  • server.charset.in and server.charset.out have been implemented
  • Some properties have been implemented to configure the server - client communication and the options offered by the server to the client.
    • server.status.request configure the strings used to request a status message; multiple strings may be listed using db.listseparator; if empty, the status feature will be disabled.
    • server.help.request configure the strings used to request a help message;
    • server.html.use use the -f option?
      • -1|no|false: do not use it and raise a error if -f is present in the request
      • 0|ignore: do not use -f; simply ignore the presence of -f in a request
      • 1|true|yes: use it
    • server.recursive.use use the -r option?
    • server.type.use use the -T option?
    • server.type.simulate simulate the -T optione?
      if this is TRUE and server.type.use is NOT TRUE, the server will try to use the first word in a request line as a type definition
      a request line like dn xyz.tld will evaluate to -T dn xyz.tld
  • db.transformnames: transform the field- / columnnames in the response
    Recognized values;
    • 0 empty do nothing
    • -1 lower lowercase tolower tolowercase uncapitalize uncapitalized to lower case
    • 1 upper uppercase toupper touppercase capitalize capitalized to upper case
  • Some efforts have been made to handle database-types that return collumn names in upper case syntax. This way a configuration file may work without changes on a different DB type. This feature may be still incomplete!
Release-Notes for Version 0.3.1.0:
  • This Version introduces the option to use velocity templates in order to format the output of JWhoisServer. This way the registrar running JWhoisServer will have a simple and flexible opportunity to customize the output according their needs. Together with the flexible configuration regarding the database structure JWhoisServer should run on, this should make JWhoisServer ready for a wide public use.
    JWhoisServer requires min. version 1.5 of Velocity because of the changed logger support (see informations on the velocity page)
    Velocity is not required by JWhoisServer to run! If you do not intend to use Velocity templates, there is no need to install Velocity!
  • Starting from this version, the compatibility for java version 1.4 was removed! The minimum java version required is now 1.5/5.0!
Release-Notes for Version 0.3.0.0:
This version introduces inetlookups for JWhoisServer.
Querying JWhoisServer with a IP, the result may look like:
$ whois -h localhost -- -r -T inet 192.168.0.22 handle: INET192.168.0.0/24 network: 192.168.0.0/24 inetnumstart: 192.168.0.0 inetnumend: 192.168.0.255 descr: 192.168.0.0/255.255.255.0 * 192.168.0.0/24 source: LOCAL ---------------------------- handle: INET192.168.0.0/23 network: 192.168.0.0/23 inetnumstart: 192.168.0.0 inetnumend: 192.168.1.255 descr: 192.168.0.0/255.255.254.0 * 192.168.0.0/23 source: LOCAL ---------------------------- handle: INET192.168.0.0/16 network: 192.168.0.0/16 inetnumstart: 192.168.0.0 inetnumend: 192.168.255.255 descr: 192.168.0.0/255.255.0.0 * 192.168.0.0/16 source: LOCAL
jump to the table of contents
1. Installation
1.1 Prerequisites

Running JWhoisServer requires: Building JWhoisServer from source additionally requires: To install this all on a debian system, run:
apt-get install mysql-server velocity liblog4j1.2-java libmysql-java whois apt-get install ant openjdk-7-jdk
jump to the table of contents
1.2 GnuPG / PGP Key

All files released are signed using my sf.net GnuPG key.
In order to verify the integrity of the files downloaded, you should import the key:
gpg --keyserver subkeys.pgp.net --recv-key ED7D414C
or
wget -O - http://jwhoisserver.net/key.asc | gpg --import -
jump to the table of contents
1.3 Installation From Source

Download the source-file JWhoisServer-VERSION-src.tar.gz
You may download the signature for the file and verify it: gpg --verify JWhoisServer-VERSION-src.tar.gz.asc JWhoisServer-VERSION-src.tar.gz
Extract the source package:
tar xvz -f JWhoisServer-VERSION-src.tar.gz
Change working directory into the build of the extracted source directory:
cd JWhoisServer-VERSION/build
Use the following command to get some help about how to configure the right classpath and install-dirs:
ant help-classpath ant help-install
A comfortably way to configure some parameters may be to edit the file build.properties or to pass them to the ant invocation.
Build and install:
ant -Dpackage.log4j.jar=/usr/share/java/log4j.jar \ -Dpackage.jdbc.jar=/usr/share/java/mysql-connector.jar \ -Dpackage.velocity.jar=/usr/share/java/velocitylibs/velocity-1.6.2/velocity-1.6.2.jar \ -Dpackage.velocity.deps=/usr/share/java/velocitylibs/velocity-1.6.2/velocity-1.6.2-dep.jar \ -Dpackage.installdir.etc=/etc/jwhoisserver \ -Dpackage.installdir.init=/etc/init.d \ jar install
If you like to use for example postgreSQL instead of mysql, you must point the package.jdbc.jar property to the jdbc-jar for pgsql:
ant -Dpackage.log4j.jar=/usr/share/java/log4j.jar \ -Dpackage.jdbc.jar=/usr/share/java/postgresql.jar \ -Dpackage.velocity.jar=/usr/share/java/velocitylibs/velocity-1.6.2/velocity-1.6.2.jar \ -Dpackage.velocity.deps=/usr/share/java/velocitylibs/velocity-1.6.2/velocity-1.6.2-dep.jar \ -Dpackage.installdir.etc=/etc/jwhoisserver \ -Dpackage.installdir.init=/etc/init.d \ jar install
Remark that the install target requires root privileges!
jump to the table of contents
1.4 Installation using .deb-Packages

The debian packages are tested with debian lenny, debian squeeze and ubuntu 9.10

Since version 0.4.0.3 there exists 4 debian packages: (in version 0.3.3.0 the jwhoisserver-utils package was renamed to libjwhoisserver-utils-java)
 
In order to verify the signatures, please import the key:
gpg --export --armor ED7D414C | apt-key add - ;
As a convenient and easy option for installation and updates, we provide a experimental deb repository for JWhoisServer.
Add the line deb http://repo.jwhoisserver.net/deb ./ to the file /etc/apt/sources.list in order to use the repository.

Install required packages:
aptitude install debconf liblog4j1.2-java libmysql-java sun-java6-jre whois debianutils dbconfig-common
If you like JWhoisServer to use a local mysql database, you will have to install mysql-server:
aptitude install mysql-server
If you like to use velocity, you will have to install velocity:
aptitude install velocity
WARNING: debian lenny has only velocity version 1.4, but JWhoisServer requires min. 1.5! You may download the original libs and adjust the CLASSPATH in /etc/defaults/jwhoisserver or use the packages from squeeze/sid using apts pinning feature.
Download the .deb-packages for the server and the utils and install it:
dpkg -i libjwhoisserver-utils-java_VERSION_all.deb dpkg -i jwhoisserver_VERSION_all.deb
or install from the repository:
aptitude install jwhoisserver
If you decide to use a local database answer yes to the question if dbconfig should automatically configure the database!
Additionally you may install the tools:
dpkg -i jwhoisserver-tools_VERSION_all.deb
or
aptitude install jwhoisserver-tools
jump to the table of contents
1.5 Installation using .rpm-Packages

Install all required software using your favourite package manager before you install JWhoisServer!
At the moment we supply RPMs for opensuse and fedora.
If not yet done, import the key for RPM:
rpm --import http://jwhoisserver.net/key.asc

Download the .rpm-packages matching your distribution, verify and install them:
rpm --checksig jwhoisserver*-VERSION-RELEASE*.rpm rpm -i jwhoisserver-utils-VERSION-RELEASE.noarch.rpm rpm -i jwhoisserver-VERSION-RELEASE.noarch.rpm
Additionally you may like to install the tools:
rpm -i jwhoisserver-tools-VERSION-RELEASE.noarch.rpm

1.5.1 OpenSUSE .rpm-Packages

You may like to add the OpenSUSE YUM repository for JWhoisServer to YAST.
Use http://repo.jwhoisserver.net/opensuse/ as the URL for the repository.
After doing this, you can install and update JWhoisServer using YAST.
1.5.2 Fedora .rpm-Packages

In order to use YUM to install JWhoisServer, you should add the YUM repository for Fedora to the repository list.
/etc/yum.repos.d/jwhoisserver.repo
[jwhoisserver] name=JWhoisServer YUM repository baseurl=http://repo.jwhoisserver.net/fedora/ enabled=1 gpgcheck=1 gpgkey=http://jwhoisserver.net/key.asc
Then you can run:
yum update; yum install jwhoisserver jwhoisserver-tools;
jump to the table of contents
1.6 Installation of the .jar from a maven repository

We provide a small maven repository holding the current version of JWhoisServer as a JAR file containing the server and the utils.
Use http://repo.jwhoisserver.net/m2/ as the URL for the repository.
The coresponding parts of a pom.xml may look like this:
<repositories> <repository> <id>jwhoisserver</id> <url>http://repo.jwhoisserver.net/m2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>net.jwhoisserver</groupId> <artifactId>jwhoisserver</artifactId> <version>0.3.3.0</version> </dependency> </dependencies>
For versions prior to 0.3.3.0, use JWhoisServer as artifactId!
jump to the table of contents
1.7 Installation on Microsoft Windows using the installer

The provided installer has to be considert as beta.
The installer has been tested on Windows XP Pro and Windows 7 Enterprise x64.
After installation you will have to configure the server (and the Database) and set the registered service to autostart if desired.
jump to the table of contents
1.8 Upgrade

If you installed the .deb-package and choose to let dbconfig do the work for you this step is obsolete for you, so please skip it!

If you upgrade JWhoisServer from a previous version take a look at the sql-directory for files named update_$version.sql.
$version refers to the current version of JWhoisServer.
So if you upgrade from 0.2.0.0 to 0.3.0.0 you will have to apply the script update_0.3.0.0.sql.
mysql -u root -p jwhoisserver < update_0.3.0.0.sql

Multiple update-files have to be applied in sequential order starting from the lowest version.
The required SQL-scripts may be found at different locations depending on the installation type:
SRC sql directory of the extracted source
DEB /usr/share/doc/jwhoisserver/
RPM /usr/share/doc/packages/jwhoisserver/
jump to the table of contents
2. Configure Database

JWhoisServer uses a mysql database as storage backend. This requires some additional configuration steps. The description provided here assume that the database will be installed on the same host running JWhoisServer, but you can use a mysql-database running on a remote host.
2.1 Create Database and User

If you installed the .deb-package and choose to let dbconfig do the work for you this step is obsolete for you, so please skip it.
The required SQL-scripts may be found at different locations depending on the installation type:
SRC sql directory of the extracted source
DEB /usr/share/doc/jwhoisserver/sql/
RPM /usr/share/doc/packages/jwhoisserver/sql/
The default scripts are for mysql. For different DB-types you may find the scripts in the subdirectories or tgz-archives named according to the DB-type, but this scripts may be incomplete.
Here a short description of the SQL-scripts: To create the database, user and table use the following commands:
mysql -u root -p < db.sql mysql -u root -p < user.sql mysql -u root -p jwhoisserver < struct.sql mysql -u root -p jwhoisserver < data.sql
To insert a small dataset for testing, read in test.sql
mysql -u root -p jwhoisserver < test.sql
jump to the table of contents
2.2 Configure DB-Settings for JWhoisServer

To configure JWhoisServer to use the current created database edit the configuration file (default: /etc/jwhoisserver/server.cfg) and adjust the following settings if required (the values shown here are the defaults):
db.type=mysql db.host=localhost db.port= db.name=jwhoisserver db.user=jwhoisserver db.pass=jwhois
For additional settings see: server.cfg or sample.cfg
jump to the table of contents
3. Start and Test it ...

First test if JWhoisServer is configured right by starting JWhoisServer as user root (if you have installed JWhoisServer from source and configured an non-standard bin-directory, you may need to invoke jwhoisserver using the full path):
jwhoisserver
If the server starts fine, try your first query:
whois -h localhost -- test.tld
3.1 init-script for jwhoisserver

If every thing works, you may use the init-script /etc/init.d/jwhoisserver to start and control JWhoisServer:
# /etc/init.d/jwhoisserver Usage: /etc/init.d/jwhoisserver {start|stop|restart|force-reload|status|stats|statistics}
status and stats|statistics require a whois-client in PATH
jump to the table of contents
3.2 Command Line Arguments for jwhoisserver

Command-Line arguments understood by JWhoisServer:
# jwhoisserver -? Java Whois Server 0.4.0.0 (c) 2006 - 2014 Klaus Zerwes zero-sys.net Syntax: jwhoisserver [-h|-?] [-L] [-V] [-p|-j] jwhoisserver [-v|-d|-s|-q] [-c cfg [-c cfg [...]]] [-l lcgf] [-P p=v [-P p=v]] -c cfg run using configuration from file cfg instead of the default: /etc/jwhoisserver/server.cfg this option may be repeated several times; the files will be read in the order of occurence on the command line (properties will be replaced) -l lcfg run using configuration for log4j from file lcfg instead of the default: /etc/jwhoisserver/log4j.cfg -P p=v set the property 'p' to the value 'v' this option may be used multiple times -d debug -v verbose -s silent -q quiet -h|-? display help -L display license -V display version -p print configuration -j print a list of supported database types
jump to the table of contents
3.3 Exit Codes of jwhoisserver

0OK
1ERROR: syntax error in invocation (wrong argument / missing parameter / ...)
2ERROR: connection to the db failed
3ERROR: unable to open socket
4ERROR: unsupported db.type
5ERROR: unsupported db.$DISPLAYOBJ.dspobj
6ERROR: config file not found or not readable
10ERROR: wrong server.bind
11ERROR: wrong server.port
12ERROR: syntax error at server.stats.allowfrom
13ERROR: syntax error at server.html.allowfrom
14ERROR: syntax error at server.shutdown.allowfrom
15ERROR: db.objectlookupdefault has wrong value(s)
17ERROR: syntax error at server.stats.numformat
18ERROR: server.stats.numformat not set
19ERROR: syntax error for a SimpleDateFormat pattern
20ERROR: syntax error for the value of fieldlength in the global scope or for a displayobject
21ERROR: syntax error in config for maxlenght value of a querytype
22ERROR: syntax error in config for regex value of a querytype
23ERROR: syntax error in config for lookupallowfrom value of a querytype
24ERROR: syntax error in config for db.fkey.identify
25ERROR: syntax error in config for server.loglevel.[connect|main|db]
26ERROR: syntax error in config for server.buffer
27ERROR: syntax error in config for server.stats.memconverter
28ERROR: syntax error in config for server.sotimeout
30ERROR: sql syntax error while building prepared statements
31ERROR: missing prepared statement
39ERROR: syntax error in config for transformquery value of a querytype
40ERROR: the velocity template dir must exist and be readable if server.velocity.use is true
41ERROR: init VelocityEngine
42ERROR: velocitytemplate not found
43ERROR: velocitytemplate parser error
44ERROR: velocitytemplate error
50ERROR: the directory defined in server.dbtypes.dir must exist and be readable
51ERROR: server.dbtypes.glob syntax error
52ERROR: DBServerType config file syntax error
100ERROR: error closing socket on shutdown
A up-to-date list may be found in the file EXITCODES.txt
jump to the table of contents
3.4 Syntax of the whois-requests

$ whois -h localhost -- help # HELP # SYNTAX: whois [-h hostname] [-r] [-f] [-T t] key # -r suppress recursion in lookups # -f generate html-formatted display (maybe restricted access) # -T t lookup only for specified type t # implemented types: # dn|domain domain (default) # key lookup for key # special keys: # HELP|? display this help # STATUS display status information # STATS display statistical informations (restricted access)
"implemented types" depend on the configuration of JWhoisServer.
since version 0.3.1.0 a new config property is available:server.clienthelp.adjust If this is set to true | 1 | yes, the help output send to the client will be adjusted according the ACLs.
Some lookups may be restricted using ACLs. See sample.cfg for details.
jump to the table of contents
4. Advanced Configuration

For a complete List of available configuration properties see sample.cfg and / or the output of jwhoisserver -p
4.1 Advanced Configuration

The provided DB-schema is only a sample. In fact JWhoisServer may be configured to run on many different DB-schemas according to the registrar's DB structure.
4.1.1 Configure Display-Objects

JWhoisServer uses so called display-objects.
The starting point for configuring display-objects is the configuration property db.objectlist. This should contain names of possible display-objects (usually tables). To configure multiple display-objects use a list separated by the value of db.listseparator (default: ;).
Example:
db.objectlist=domain;person;mntnr;nameserver

Each defined display-object may be configured using a subset of properties to db.$OBJECTNAME:
property description example
.table SQL - table name for object; defaults to $OBJECTNAME db.domain.table=domain
.key Name of the key (used for key-queries); defaults to ${table}_key db.domain.key=domain_key
.qfield Define the query field for non-key-queries. (defaults to $OBJECTNAME) db.domain.qfield=domain
.transformquery if .objectlookup is configured, transform the request (default: to lower case)
  • to lower case: -1 lower lowercase tolower tolowercase uncapitalize uncapitalized
  • to upper case: 1 upper uppercase toupper touppercase capitalize capitalized
  • do nothing: 0 ignore keep leave untouched
db.domain.domain=lower
.display SQL - field-list used to display this object separated by db.listseparator. (defaults to $OBJECTNAME) The key will always be included in the query, he output is configurable by .handleprefix db.domain.display=domain;mntnr_fkey;changed
.displayshort SQL - field - list used to generate a "non-recursive" display of this object separated by db.listseparator. If not configured, .display will be used. This will be used to generate the display for non-recursive lookups. domain;'active' AS status
.handleprefix String as prefix for key to generate unique handle; If this property is set (even if it is a empty string) the key of the object will be displayed prefixed by the value of the property. If the property is not configured, the key will be excluded from the output. db.domain.handleprefix=DMN
.objectlookup If this object should be a lookup-object (selectable via -T), configure a list of lookup definitions separated by db.listseparator db.domain.objectlookup=domain;dn
.lookupallowfrom If this object is configured as a lookup and you like to restrict access to this lookup - type, list the IPs/networks allowed here separated by db.listseparator. IPs/networks may be single host or networks in CIDR (/25) or dotted decimals notation. db.person.lookupallowfrom=10.10.10.101;192.168.2.0/24
.match If this object is configured as a lookup you may like to define a regular expression to match a lookup. db.domain.match= ^[a-z0-9]?+tld$
.maxlength Maximum allowed length of a lookup. db.domain.maxlength=255
.match.errorstring String to be displayed as a error message if a lookup fails to match defined regular expression. db.domain.match.errorstring=ERROR\r\n
.parent.$PARENTOBJECTNAME Define a SINGLE fieldname that will be used as a foreign key for the display-object $OBJECTNAME. The data will be displayed inline, that means instead of the defined field using a non-key-query on the object $PARENTOBJECTNAME. db.domain.parent.nameserver=domain_fkey
.recursecondition Define a SINGLE fieldname. The field will be added to the query for $OBJECTNAME and if the value for the field will not evaluate to "true" or 1 recursion will be disabled. db.domain.recursecondition=publicviewabledata
.recurse.$RECURSEOBJECTNAME Define a list of fields; Each field will be handled as a key for $RECURSEOBJECTNAME and a new display-object of type $RECURSEOBJECTNAME will be generated using a key-query. db.domain.recurse.person=holder;admin_c;tech_c;zone_c
.whereaddition Additional string to be appended to WHERE-part of the query. db.domain.whereaddition=\ AND disabled \= 0
.tablejoin Additional string appended after SELECT ... FROM tablename (useful for joins) db.person.tablejoin= LEFT JOIN country ON country_key\=country_fkey
.matchkey stupid sql driver: if you use tablename.fieldname in the select statement, getColumnLabel reports only fieldname so we need a special test some times db.person.matchkey=id
Since version 0.2.0.0 there exists 2 new configuration properties effecting the handling of non-recursive foreign keys:
  • db.fkey.identify: a string identifying a foreign key column name (defaults to: _fkey)
  • db.fkey.replace: string (will be used as a replacement for db.fkey.identify) (defaults to empty string)
These properties are considered as experimental and may be changed or removed in the future. They will be probably be extended per table/object.

Since version 0.3.0.0 there exists 2 special configuration properties regarding inetlookups:
  • db.inetnum.bytelength: a string defining the fieldname for the bytelength value (defaults to: bytelength).
  • db.$OBJECTNAME.dspobj: a string defining the displayObject class to load for this object (default: db.inetnum.dspobj=net.jwhoisserver.server.DisplayObjectInetNum)
    For the future I plan implementing a plugin-system for DisplayObjects that will make use of this property.

Since version 0.3.3.0 the server may be configured for multiple default lookuptypes:
db.objectlookupdefault: a list of default lookuptypes separated by the value of db.listseparator (default: ;).
This property is used, in case the server recieves a request without a defined lookuptype (i.e. without the -T option).
In this case, we will loop all displayobjects from the list and will use the first where the request string matches the configured regex. Therefore only the last element from the list may have a empty regex (as this will always match).
4.1.2 Configure output format

The output of JWhoisServer can be customized to some extend using some properties. If you need more flexibility, you may use velocity templates.
This is a list of some properties usefull for formatting the output of JWhoisServer:
db.namevalueseparator The value of this property is used to separate the fieldname and the value. Defaults to colon (:) db.namevalueseparator=\:
db.paddstring The value of this property is used to rightpadd the fieldname up to the configured fieldlength. Defaults to whitespace db.paddstring=\
db.fieldlength This property configures the length of the field name. paddstring will be used to right padding the field name up to the configured length. db.fieldlength=12
db.transformnames Transform the field- / columnnames in the response. Recognized values:
  • 0 empty do nothing
  • -1 lower lowercase tolower tolowercase uncapitalize uncapitalized to lower case
  • 1 upper uppercase toupper touppercase capitalize capitalized to upper case
db.transformnames=upper
Since 0.3.1.1: db.fieldlength, db.paddstring and db.namevalueseparator are global settings. They may be changed on a per displayobject level using:
  • db.$OBJECTNAME.fieldlength
  • db.$OBJECTNAME.paddstring
  • db.$OBJECTNAME.namevalueseparator
Since version 0.3.1.1 JWhoisServer supports customizable formatting of Date-Fields in the output.
Fore each defined displayobject $OBJECTNAME you can define a SimpleDateFormat pattern for each field you have configured using db.$OBJECTNAME.display and db.$OBJECTNAME.displayshort
For each field defined a format pattern using
db.$OBJECTNAME.dateformat.display.$FIELDNAME=FORMATPATTERN or
db.$OBJECTNAME.dateformat.displayshort.$FIELDNAME=FORMATPATTERN
depending where you have defined $FIELDNAME.
 
See http://java.sun.com/javase/6/docs/api/index.html?java/text/DateFormat.html for details about the format patterns.
If you define a column in db.$OBJECTNAME.display and db.$OBJECTNAME.displayshort as a alias, you must refer to the alias of the fieldname in db.$OBJECTNAME.dateformat.display.$FIELDNAME or db.$OBJECTNAME.dateformat.displayshort.$FIELDNAME.
This rule applies to other config properties too!
db.domain.display=domain;changed AS lastchanged db.domain.dateformat.display.lastchanged=...
Example:
db.domain.fieldlength=20 db.domain.paddstring=. db.domain.dateformat.display.last\ changed=EEE, d MMM yyyy HH:mm:ss Z db.domain.display=domain;mntnr_fkey;changed AS "last changed"; db.nameserver.fieldlength=25 db.nameserver.paddstring=+ db.nameserver.namevalueseparator=#
will result in a output like this:
domain:.............test10.tld mntnr:..............MNTNR1 last changed:.......Thu, 17 Dec 2009 16:14:24 +0100 nameserver#++++++++++++++ns1.ns10.tld nameserver#++++++++++++++ns2.ns10.tld nameserver#++++++++++++++ns3.ns10.tld
Since version 0.3.2.3, JWhoisServer supports customizable output for fields holding multiple lines.
Fore each defined displayobject $OBJECTNAME you can define a list of fileds that should be handled as multi-line fileds.
db.$OBJECTNAME.multilinefields=filed1;filed2;...
For each field defined here you can configure:
  • the line delimiter (defaults to \n)
    db.$OBJECTNAME.multilinefield.$FIELDNAME.lineseparator=\\n
  • how the lines shouldbe formated using db.$OBJECTNAME.multilinefield.$FIELDNAME.usespaces expecting a boolean value (defaults to false)
    • false - the fieldname will be repeated
    • true - lines form the second one will be padded using the paddstring defined
Example:
db.person.multilinefields=address
will result in a output like this:
address: street address: city address: country
Example:
db.person.multilinefields=address db.person.multilinefield.address.usespaces=true
will result in a output like this:
address: street city country
jump to the table of contents
4.2 Configure JWhoisServer for inetlookup

This chapter is about a new extension since version 0.3.0.0: inetlookup
This feature should be considered as "work in progress".
4.2.1 Configuration properties for inetlookup

In order to enable inetlookup for jwhoisserver you will have to set some configuration properties. If you prefer to run a server only for inetlookup (i.e. no domain-lookups), see inetsample.cfg.
property value description
db.objectlist domain;inetnum;person;mntnr;nameserver extend the objectlist by inetnum
db.inetnum.table inetnum define the table for inetnum
db.inetnum.objectlookup inetnum;inet define the lookup type
db.inetnum.dspobj net.jwhoisserver.server.DisplayObjectInetNum define the class to be used for generating the display!
db.inetnum.qfield inetnumstart define the queryfield
db.inetnum.key netname define the key
db.inetnum.handleprefix INET define the prefix for the inetnum-handle
db.inetnum.bytelength bytelength define the field for the bytelength of a inetnum-object
db.inetnum.display netname AS network;bytelength;inetnumstart;inetnumend;descr;source define the display-fields
db.inetnum.recurse.person admin_c;tech_c recursive fields (foreign keys targeting the person table)
db.inetnum.match \\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}(/[0-9]{1,2})*\\z the regex to match a query string (see sample.cfg for IPv6 regex)
4.2.2 Notes regarding the MySQL-Table for inetlookup

The table for inetlookup (inetnum) is only implemented for mysql, postgresql and hsqldb. If you need this using another RDBMS, you must create the table on your own!
The default table is only suitable for IPv4 values, as it uses INTEGER UNSIGNED for inetnumstart and inetnumend. If you need to store values for IPv6, you must change the type of this two fields to DECIMAL( 39, 0 ) UNSIGNED! (see: inetnumIPv6.sql)
4.2.3 Command-Line Tools

JWhoisServer includes some small helper tools for inetlookup and IDN/ACE transformation:
  • IPCalc: a simple commandline tool to get a description of a network
  • IP2UBI: convert one or more IPs to Unsigned Big Integer: for IPv4 this is compatible to the mysql-function INET_ATON
  • UBI2IPv4: convert a Unsigned Big Integer to a IPv4: compatible to the mysql-function INET_NTOA
  • UBI2IPv6: convert a Unsigned Big Integer to a IPv6
  • IDN2ACE: convert a IDN string into his ACE representation (nameprep + punycode)
  • ACE2IDN: convert a ACE string into his IDN representation (inverse punycode)
  • ClasspathTransform4Jar: convert a (OS dep.) CLASSPATH string containing only absolute paths into a string usable for the Class-Path directive in the MANIFEST of a jar-file.
Like jwhoisserver, all this tools have a small man-page. If you installed using a .deb or .rpm, you can access the manpages in the usual way using the man command. Otherwise you can find the man-pages in the debian/ directory of the source package (unfortunately there is no install-doc target for the build).
4.2.4 API regarding the InetLookup stuff

The API for some helper classes developed for jwhoisserver, that may (or may not) be useful for others, can be found at http://jwhoisserver.sourceforge.net/api/
The API documents:
  • InetIP2UBI: contains static functions to convert inetaddress 2 unsigned big int and back
  • InetNetwork: A utility class for InetAddress representing a network as a range of InetAddresses starting from a IP address and a netmask.
  • IP2UBI: main class for the tool with the same name
  • IPCalc: main class for the tool with the same name
  • UBI2IPv4: main class for the tool with the same name
  • UBI2IPv6: main class for the tool with the same name
jump to the table of contents
4.3 Configure JWhoisServer for Velocity

This chapter is about a new extension since version 0.3.1.0: Velocity Templates
In order to use Velocity Templates, JWhoisServer requires min. Velocity Engine version 1.5. The recommended version is 1.6.2.
This feature should be considered as "work in progress".
4.3.1 Configuration properties for velocity

property value description
server.loglevel.velocity -1 finetuning of the loglevel for the velocity engine:
5 - fatal; 4 - error; 3 - warn, 2 - info; 1 - debug; 0 - OFF; -1 use the global loglevel
server.velocity.use false|no|0|true|yes|1 enable / disable the usage of velocity; the default value is:false
server.velocity.dir /etc/jwhoisserver/velocity/ the directory where the templates are stored
server.velocity.cfg path to a special property file that should be passed to velocity
server.velocity.template.error the name of the error template; if none defined, no template will be used
server.velocity.template.help the name of the help template; if none defined, no template will be used
server.velocity.template.status the name of the status template; if none defined, no template will be used
server.velocity.template.stats the name of the statistics template; if none defined, no template will be used
server.velocity.template.default the name of the template for the display-objects; if none defined, no template will be used
server.velocity.template.$OBJECTNAME the name of the template that should be used for lookups for $OBJECTNAME; if none defined, server.velocity.template.default will be used
4.3.2 Objects made available to the Velocity Templates

For all templates the $server object is available (represents: VelocityWrapper) and offers some functions:
Method Summary
 java.lang.String getAverageStats()
           
 java.lang.String getBanner()
           
 java.lang.String getClientHelp()
           
 java.net.InetAddress getClientInetAddress()
          get the clients InetAddress
 java.lang.String getClientInetAddressString()
           
 java.lang.String getConStats()
           
 long getCounterACLviolations()
           
 long getCounterClientErrors()
           
 long getCounterClientTime()
           
 long getCounterConnections()
           
 long getCounterConnErrors()
           
 long getCounterConnTimeout()
           
 long getCounterDBConnect()
           
 long getCounterDBErrors()
           
 long getCounterRegexErrors()
           
 long getCounterRequestsHelp()
           
 long getCounterRequestsHTMLFormat()
           
 long getCounterRequestsNonRecursive()
           
 long getCounterRequestsRecursive()
           
 long getCounterRequestsStats()
           
 long getCounterRequestsStatus()
           
 long getCounterSQLErrors()
           
 long getCounterSQLStatements()
           
 long getCounterSQLTime()
           
 java.lang.String getLegal()
           
 java.lang.String getLookupKey()
           
 java.lang.String getLookupType()
           
 java.lang.String getMemStats()
           
 java.lang.String getRequest()
           
 java.lang.String getStats()
           
 java.lang.String getUptime()
           
 java.lang.String getVersion()
           
 boolean isHtmlFormat()
           

server.velocity.template.error-Template has in addition 2 variables:
  • $errormsg: the error message generated for the client
  • $errorcode: the error code:
    • 1 bad client behaviour
    • 2 ACL deny
    • 3 missing or unknown argument to -T
    • 4 error parsing request
    • 5 no search key supplied (in fact code error 1 should catch this ???)
    • 6 internal error
    • 10 regex error for displayobject

server.velocity.template.status-Template has one additional variable:
  • $statusmsg: the status message

for the server.velocity.template.default and server.velocity.template.$OBJECTNAME-Templates there is a complex data-structure available:
  • $display: a VelocityDisplayLookup-Object holding all the data that may be used to generate a result-page.
    Method Summary
     int getErrorCode()
              get the error code: 0 - everything is OK 1 - bad client behaviour 2 - ACL deny 3 - missing or unknown argument to -T 4 - error parsing request 5 - no search key supplied (in fact code error 1 should catch this ???) 6 - internal error 10 - regex error for displayobject
     java.lang.String getErrorMessage()
              get the error message
     java.lang.String getLookupType()
              Get the lookup type requested by the client: domain, inet, ...
     java.lang.String getLookupValue()
              get the value of the lookup
     java.util.Vector<VelocityDisplayObject> getResultList()
              Get all results as a Vector of VelocityDisplayObjects
     int rowsCount()
              get the number of results found
  • each VelocityDisplayObject - object used by the $display provides some methods:
    Method Summary
     java.util.HashMap<java.lang.String,java.util.Vector<VelocityDisplayObject>> getAllParentObjects()
              get all parent objects as a HashMap: table-name => Vector of VelocityDisplayObjects
     java.util.HashMap<java.lang.String,java.util.Vector<VelocityDisplayObject>> getAllSubObjects()
              get all sub-objects as a HashMap foreign key name => Vector of VelocityDisplayObjects
     java.util.LinkedHashMap<java.lang.String,java.lang.String> getDisplayMap()
              get the result for this object as a Map field-name => field-value
     int getErrorcode()
              Error code for this object: 0 - no error; 1 - error
     java.lang.String getErrormsg()
              Error message for the error occurred for this Object
     java.lang.String getName()
              get the name of the obj.
     VelocityDisplayObject getNextSubObject(java.lang.String fkey)
              get the first VelocityDisplayObject for the specified foreign key and delete it from the vector
     java.util.Vector<VelocityDisplayObject> getParentObjects(java.lang.String parentname)
              Get a Vector of VelocityDisplayObjects for a specified parent table name
     java.lang.String getQfield()
              get the query-field
     java.util.Vector<VelocityDisplayObject> getSubObjects(java.lang.String fkey)
              get the Vector of VelocityDisplayObjects for the specified foreign key
     java.lang.String implodeParentObjects(java.lang.String parentname, java.lang.String field)
              get a list of all values for the specified field from the table parentname separated by spaces
     java.lang.String implodeParentObjects(java.lang.String parentname, java.lang.String field, java.lang.String delimiter)
              get a list of all values for the specified field from the table parentname separated by delimiter
Since version 0.4.1.2 a new optional config setting is available: server.velocity.context
It may be configured as a list of class names that should be made available in the velocity context.
Example:
server.velocity.context=org.apache.commons.lang.WordUtils
will put a instance of org.apache.commons.lang.WordUtils into the velocity context as WordUtils
jump to the table of contents
4.4 Configure a additional lookup

Lets assume you want to enable lookups on the person-object from localhost, then you should extend your config:
db.person.objectlookup=person;pn db.person.qfield=name db.person.lookupallowfrom=127.0.0.1
and try it out:
$ whois -h localhost -- -T pn persona non grata This is JWhoisServer serving ccTLD tld Java Whois Server 0.0.3.0 (c) 2006 - 2007 zero-sys.net Klaus Zerwes ... handle: PRSN1 mntnr: MNTNR1 type: PERSON name: persona non grata address: two dead ends pcode: NWR country: AX phone: +77 31 123454321 fax: +77 31 123454321 email: mail@domain.tld changed: 2006-10-14 16:20:00
As you can see the HELP-reply of the server will get automatically updated:
$ whois -h localhost -- help # HELP # SYNTAX: whois [-h hostname] [-r] [-f] [-T t] key # -r suppress recursion in lookups # -f generate html-formatted display (maybe restricted access) # -T t lookup for specified type t # implemented types: # dn|domain domain (default) # pn|person person # key lookup for key # special keys: # HELP|? display this help # STATUS display status information # STATS display statistical informations (restricted access)
jump to the table of contents
4.5 Configure JWhoisServer to run on a different database structure

Using the informations above, you can configure JWhoisServer to run on your own database using your defined data-structure.
The SQL statement are build this way:
Let's have a look on a sample database:
sample DB
The goal of the configuration is to provide:
  1. a recursive domain lookup including informations about the handles assigned to the domain
  2. a simple non-recursive domain lookup
  3. a handle lookup
Let us start configuring the displayobjects: db.objectlist=domain;handle;handlelookup
Next step: configuring the domain object
db.domain.table=domains db.domain.objectlookup=dn;name db.domain.qfield=name db.domain.key=id db.domain.display=name;rdate AS registered;edate AS expires;cdate AS changed; db.domain.displayshort=name;'connected' AS status db.domain.recurse.handle=id db.domain.whereaddition=
Next step: configuring the recursion to the handles
db.handle.table=domain_handle_relation db.handle.key=did db.handle.display=type;handle;name;firstname db.handle.tablejoin=\ JOIN handles ON hid=handles.id JOIN type ON tid=type.id
Next step: configure the lookup for the handles
db.handlelookup.table=handles db.handlelookup.objectlookup=handle db.handlelookup.qfield=handle db.handlelookup.key=id db.handlelookup.display=handle;name;firstname
Using the -d argument for the startup of JWhoisServer will enable debug and will print all SQL statements.
jump to the table of contents
5. Notes: java versions

The recommended java runtime to run JWhoisServer is
Except some special features the server should run on sun jre 1.5/5.0.
Support for java version 1.4 was dropped since version 0.3.1.0!
Short tests have been done using gij-4.3.
Older versions have been (more or less) successfully tested using gij 4.1, SableVM (1.13), JamVM (1.4.4) and kaffe VM (1.1.7).
jump to the table of contents
6. Notes: Log Levels

The default LogLevel is WARN.
There are 2 ways to configure the log levels:
  1. using command line args:
    1. -d : debug - this will set the LogLevel to DEBUG
    2. -v : verbose - this will set the LogLevel to INFO
    3. -s : silent - this will set the LogLevel to FATAL
    4. -q : quiet - this will set the LogLevel to OFF
  2. using configuration properties:
    1. server.loglevel.connect
    2. server.loglevel.main
    3. server.loglevel.db
    4. server.loglevel.velocity
    each of these properties may have one of the following values:
    5Loglevel: FATAL
    4Loglevel: ERROR
    3Loglevel: WARN
    2Loglevel: INFO
    1Loglevel: DEBUG
    0Loglevel: OFF
    -1use the global Loglevel
    Example: set server.loglevel.connect=0 to disable logging connections.
jump to the table of contents
7. Notes: Performance

Here are some (older) stats:
OS CPU MEM java version Notes
Linux (debian lenny) 2x Intel Xeon E5405 @ 2.00GHz 4 G Sun Java 1.6.0_12
  • some test clients running on same device
  • no velocity templates used
uptime: 0 days 17:55:52 (64552 seconds); dbconn:1 mem used / avail / max: 22261 / 63296 / 902976 conn total: 2847331 conn errors: 0 conn timeout: 0 client errors: 0 access violations: 0 regex errors: 0 requests recursive: 1909843 requests non-recursive: 937468 requests html-formatted: 0 requests stats: 20 requests status: 0 requests help: 0 sql statements: 12396526 sql errors: 0 db errors: 0 average client time: 0.88 (2496557/2847331) average sql time: 0.07 (887912/12396526)
 
Linux (debian lenny) Pentium III @ 730 MHz 256 MB OpenJDK Runtime Environment (build 1.6.0_0-b11)
  • some test clients running on same device
  • no velocity templates used
  • java VM started with com.sun.management.jmxremote
uptime: 0 days 20:17:30 (73050 seconds); dbconn:1 mem used / avail / max: 4028 / 5056 / 520256 conn total: 4208767 conn errors: 0 conn timeout: 0 client errors: 841753 access violations: 0 regex errors: 841754 requests recursive: 1683507 requests non-recursive: 0 requests html-formatted: 0 requests stats: 841753 requests status: 0 requests help: 0 sql statements: 5892277 sql errors: 0 db errors: 0 average client time: 4.12 (17330724/4208767) average sql time: 0.93 (5476480/5892277)
Here are some screenshots of jconsole
 
Linux (debian lenny) Pentium III @ 730 MHz 256 MB OpenJDK Runtime Environment (build 1.6.0_0-b11)
  • some test clients running on same device
  • simple velocity templates used!
  • java VM started with com.sun.management.jmxremote
uptime: 0 days 18:29:35 (66575 seconds); dbconn:1 mem used / avail / max: 5291 / 8328 / 520256 conn total: 3425620 conn errors: 0 conn timeout: 0 client errors: 0 access violations: 0 regex errors: 685124 requests recursive: 2055373 requests non-recursive: 0 requests html-formatted: 0 requests stats: 685123 requests status: 0 requests help: 0 sql statements: 9591737 sql errors: 0 db errors: 0 average client time: 7.02 (24061148/3425620) average sql time: 0.82 (7828034/9591737)
Here are some screenshots of jconsole. During this test we used velocity templates.
 

Valid XHTML 1.0 Transitional valid CSS logo