Sunday, October 4, 2009

Shared SSH Keys

Shared Keys add an additional security level to using SSH and if you choose not to use a password you can automate logging in via SSH. It also allows you to completely negate brute force password cracking attempts if you disable password authentication.

This tutorial assumes a basic knowledge of the Linux Command Line. The tutorial is written for Centos 5.X but is applicable to other distributions, although file locations may be slightly different. The tutorial is targeted at Mac and Linux users.

What are shared keys?
Shared Keys consist of a Public and Private key and allow a remote machine to authenticate a machine trying to connect it. The Private key resides on your machine and is used to identify you against the public key which resides on the machine you are trying to login to. You might think of it as a handshake. The remote machine has a description of what to expect from the handshake. It is unique to the client machine so if the handshake doesn't match then the authentication will fail.

Why use shared keys?
Shared keys have two main benefits. Firstly they allow you to turn off password authentication. Malicious bots regularly crawl the web trying to login to servers using SSH. They have large dictionaries of passwords and try to get into your server using brute force attacks. You can limit this by having a strong password and changing the port that you use to login to SSH with. You can also completely turn off password authentication if you use shared keys. Shared keys mean that no one can access your server without the shared key.

The second benefit is that if you use scripts to backup your server to another one you do not need passwords to run the scripts. The scripts can just use the shared keys to authenticate.

How to do it?
On my Mac I'm logged in as the user myuser. On the remote machine I also login using the user myuser. On my Mac I open Terminal (you'll find this in Applications > Utilities). First I need to generate the keys on my machine. I run this command:
$ ssh-keygen -t rsa

You will be prompted for a password. If you don't want a password just hit return. This means however that anyone who gets control of your machine will be able to login to your server. This generates a public and a private key in a hidden folder
$/users/myuser/.ssh

It is possible that you won't be able to see hidden files on your Mac by default. If this is the case you can enable this across your system by running the commands.
$ defaults write com.apple.finder AppleShowAllFiles TRUE 
$ killall Finder

Now on the remote machine login as your user using your normal password. In your home directory (/home/myuser in this example) create a new folder and then a file to hold your authorized keys.
$ mkdir .ssh 
$ cd .ssh 
$ touch authorized_keys

Now we copy the public key to the server using the scp command. This transfers the file using SSH so is secure as no one can see it. You will be asked for your regular password.
$ scp ~/.ssh/id_rsa.pub myuser@remote_server_host_address_or_ip:~/

Now SSH into your remote server in the standard way and in your home directory (/home/myuser in this example) you will see the file id_rsa.pub. We want to import this into our list of authorized keys so on the remote machine run this command.
$ cat id_rsa.pub >> ~/.ssh/authorized_keys

This writes the contents of the key to our authorized keys list. Once you are done we want to clean things up and set permissions on the files to ensure that no one can else can use our key. On the remote machine:
$ rm id_rsa.pub 
$ chmod 700 ~/.ssh 
$ chmod 600 ~/.ssh/authorized_keys

On the local machine: File permissions on a user's /home/user/.ssh directory must be 700, and the /home/user/.ssh/authorized_keys must be 600. Meanwhile, it is essential that all files in each .ssh directory are owned by the user in whose home directory they reside. To change ownership recursively, you can:
$ chown -R username:username /home/username/.ssh
$ chmod 700 ~/.ssh 
$ chmod 600 ~/.ssh/id_rsa

If you have multiple users and need to do this for each of them, you can use this loop:
for SSHUSER in user1 user2 user3 user4 user5; do
  # Add the authorized_keys file if it doesn't already exist
  touch /home/$SSHUSER/.ssh/authorized_keys
  # Set its permissions
  chmod 600 /home/$SSHUSER/.ssh/authorized_keys
  # Set directory permissions
  chmod 700 /home/$SSHUSER/.ssh
  # Set ownership for everything
  chown -R $SSHUSER:$SSHUSER /home/$SSHUSER/.ssh
done;

You should now be set up to access your machine with your shared key. Login as normal and if all goes to plan you will be granted access with your key. You can debug logging in by adding the verbose flag to your SSH request.
$ ssh -v myuser@remote_server_host_address_or_ip

Once you are sure everything is ok you can now disable password logins for addtional security. On the remote machine you will need root access and run the following commands
$ vi /etc/ssh/sshd_config

Find the line:
$ PasswordAuthentication yes

Change this to no. Then hit escape : wq to save the file. Finally restart the sshd daemon:
$/etc/init.d/sshd restart

You will now only be able to login to your server using a shared key.

Saturday, June 27, 2009

RedHat / Centos Disable IPv6 Networking

Our policy and network configuration does not requires IPv6 support in RHEL / CentOS / Fedora Linux. How do I prevent the kernel module from loading at boot time and disable IPv6 networking?
You can easily prevent the kernel module from loading by updating the following two files:

  1. /etc/modprobe.conf - Kernel driver configuration file.
  2. /etc/sysconfig/network - RHEL / CentOS networking configuration file.

/etc/modprobe.conf
Edit /etc/modprobe.conf, enter:
# vi /etc/modprobe.conf

Append the following line:
install ipv6 /bin/true
Save and close the file.

/etc/sysconfig/network
Edit /etc/sysconfig/network, enter:
# vi /etc/sysconfig/network

Update / add as follows:
NETWORKING_IPV6=no
IPV6INIT=no

Save and close the file. Restart networking service
# service network restart
# rmmod ipv6

Alternatively, simple reboot the box:
# reboot

Verify IPv6 is disabled, enter:
# lsmod | grep ipv6
# /sbin/ifconfig

J A V A in L I N U X

Download the JDK from Oracle. The latest version as of now is Java SE 7u51.

I'm on 64-bit machine, therefore I downloaded jdk-7u51-linux-x64.tar.gz

It's easy to get the tar.gz package as we just have to extract the JDK, I usually extract the JDK to /usr/lib/jvm directory.
cd /usr/lib/jvm/
sudo tar -xf ~/Software/jdk-7u51-linux-x64.tar.gz
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.7.0_51/bin/javac" 1
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.7.0_51/bin/java" 1
sudo update-alternatives --install "/usr/lib/mozilla/plugins/libjavaplugin.so" "mozilla-javaplugin.so" "/usr/lib/jvm/jdk1.7.0_51/jre/lib/amd64/libnpjp2.so" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0_51/bin/javaws" 1

After installing, we should configure each alternative
sudo update-alternatives --config javac
sudo update-alternatives --config java
sudo update-alternatives --config mozilla-javaplugin.so
sudo update-alternatives --config javaws

Now we can configure JAVA_HOME. We can edit ~/.bashrc and add following.
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0_51/

Download Oracle JDK on Linux:
$ wget --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz --no-check-certificate
$ mv jdk-8u5-linux-x64.tar.gz?AuthParam=1399837157_13a216ce71be82d57322314c7d258f1a jdk-8u5-linux-x64.tar.gz

# it will create a directory('jdk1.8.0_05/') under default.
$ tar -zxf jdk-8u5-linux-x64.tar.gz -C /usr/java

# this will change the last modified date of directory recursively
$ find /usr/java/jdk1.8.0_05 -exec touch -t 201103161212.33 {} \;

# this will give randam date
$ find /home -exec touch -t `random` {} \;

################################################################################
[root@anuppc-01 ~]# wget --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz --no-check-certificate
--2014-05-11 19:37:17--  http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz
Resolving download.oracle.com... 23.67.251.57, 23.67.251.50
Connecting to download.oracle.com|23.67.251.57|:80... connected.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: https://edelivery.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz [following]
--2014-05-11 19:37:17--  https://edelivery.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz
Resolving edelivery.oracle.com... 23.45.38.140
Connecting to edelivery.oracle.com|23.45.38.140|:443... connected.
WARNING: certificate common name `www.oracle.com' doesn't match requested host name `edelivery.oracle.com'.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz?AuthParam=1399837157_13a216ce71be82d57322314c7d258f1a [following]
--2014-05-11 19:37:17--  http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-x64.tar.gz?AuthParam=1399837157_13a216ce71be82d57322314c7d258f1a
Reusing existing connection to download.oracle.com:80.
HTTP request sent, awaiting response... 200 OK
Length: 159008252 (152M) [application/x-gzip]
Saving to: `jdk-8u5-linux-x64.tar.gz?AuthParam=1399837157_13a216ce71be82d57322314c7d258f1a'

100%[======================================================================================================>] 159,008,252 18.4M/s   in 14s

2014-05-11 19:37:31 (10.7 MB/s) - `jdk-8u5-linux-x64.tar.gz?AuthParam=1399837157_13a216ce71be82d57322314c7d258f1a' saved [159008252/159008252]

[root@anuppc-01 ~]#
#################################################################################



Monday, May 4, 2009

Git for Windows with TortoiseGit and GitHub

For this project, we are required to use Git for version control and host code on GitHub. As a person who has always preferred SVN (for its linear/incremental nature), and have only had experience with Google Code and SourceForge, setting up a new GitHub repo was a new experience. And so, for future reference, I document the process here. In this article, we will install msysgit and TortoiseGit and host code on GitHub.

Installing TortoiseGit:

http://code.google.com/p/tortoisegit/ (yes, its hosted on Google Code) TortoiseGit is a shell extension for Windows Explorer that allows for easy management of Git projects. Its a port of the popular TortoiseSVN project, but for Git. First step would be installing Git for Windows (msysgit), which will also give you a nice, simplistic bash shell that you can work with (and execute the above commands just like on Linux if you'd prefer that over TortoiseGit). I personally just downloaded and installed Git 1.7.9 with all default settings. Next was installing TortoiseGit itself, which should autodetect the installed Git setup (though you can configure it later if you haven't) and add itself to the Windows Explorer right-click context menu.

Generating your public key:

To associate your computer with GitHub, you will need a "public key/private key" pair. You could do this entire process manually with the bash shell, but TortoiseGit gives you a handy GUI tool for it: Puttygen (PuTTY Key Generator). Run Puttygen via your Start menu: "Start -> Programs -> TortoiseGit -> Puttygen". Click "Generate", move your mouse around the blank box for a bit, and wait for the box to fill with your newly generated key. Copy the entire text in the box (right-click -> Select All, right-click -> Copy). This is your public key. Then click "Save private key" and choose a safe place to store the .pkk file (e.g. "TortoiseGit.ppk"), passphrase optional. This file stores your private key.

Adding your private key to TortoiseGit:

Next you want make your private key accessible to TortoiseGit for authenticating with GitHub. For this, we'll manage our key list with Pageant: "Start -> TortoiseGit -> Pageant". This will add an icon to your taskbar (see picture below). Right click the icon and select "View Keys". Click "Add Keys" and navigate to your previously saved PuTTY key that is storing your private key file (e.g. "D:\Development\Sandbox\TortoiseGit.ppk"). If added properly, you should see the new key added to the list.

Registering for GitHub:

https://github.com/signup/free
GitHub is a project hosting website that focuses mainly on Git. As of the moment, they offer free public repositories and unlimited public collaborators for open source projects. Registration is pretty straightforward - just sign up for a free personal account.

Adding your public key to GitHub:

https://github.com/settings/ssh
Go to your "Account Settings" on GitHub and go to the "SSH Keys" section. Click "Add SSH key" and paste your public key into the box. Give the key a descriptive title (it doesn't really matter) and then click "Add key". After confirming your GitHub password, you should see the new key added to your "SSH Keys" list.

Creating a GitHub repository:

https://github.com/repositories/new Go to your GitHub profile page (click your username on the top right) and click "New repository". Proceed to fill out the project information. Note that the "Project Name" becomes the repos name, so you may want to use a clean, space-less name (e.g. "PlanmanupNewGITProject" for this project). After clicking "Create repository", you'll be presented with a list of commands to execute to create your first commit. Since we'll be using TortoiseGit instead of a command-line to manage files, you can ignore

Creating your local repo

Now that the project has been created on GitHub, its time to create it on your computer! The GitHub page will give you bash commands for creating the new repos, but we'll use TortoiseGit instead. Navigate to the folder/drive where you want your code to be stored (e.g. "D:\Development\Sandbox"). In that folder, right click to open up the Windows Explorer context menu and select "Git clone...". In the popup box, copy-paste the Git repo URL from GitHub (see above picture) and click "OK". Since you've already set up the authentication earlier and its an empty repository, it should be quick (the log will warn you about cloning an empty repo though). If a new folder has been created with the name of your project (e.g. "D:\Development\Sandbox\PlanmanupNewGITProject"), the clone was successful!

Push files/changes to your local branch

What you have now is a clone of a branch of your repository. Your current branch is probably the master branch assuming you just created a clean project. Go ahead and add files and your code to the folder. Once you're happy with your code/changes, it's time to commit these changes. You can do so by right clicking to open up the context menu in the clone's folder and selecting "Git Commit -> "master"...". This will open up a window that will allow you to add the change message and select what changes you want to commit. If its your first commit, you will want to check the "Select/Deselect All" checkbox to add all your new files. Click "OK" when you're happy to commit the changes to your branch. Note that unlike SVN, this commit is LOCAL ONLY!

Synchronizing changes with GitHub

After a few commits, you might want to push your changes to GitHub. Open up the context menu in the clone's folder and selecting "TortoiseGit -> Push". In the new window, if you also added tags, don't forget to check the "Include Tags" checkbox before clicking "OK". If other project collaborators pushed out changes, you can pull their changes from GitHub with "TortoiseGit -> Pull".

Associating your private key with the git repos

To avoid having to manually start up the Pageant daemon every time you want to sync your git repos with GitHub, you can add your PuTTY key to TortoiseGit's Remote settings. Open up the context menu in the clone's folder and selecting "TortoiseGit -> Settings". In the new window, select "Git -> Remote" and select your Remote item (in my case, "origin"). Locate and select the .ppk file from earlier for the "Putty Key" field and click "OK". Now you don't have to manually start up Pageant every time you reboot your computer!

You're done! and that's it! If you check your GitHub project page, you should see your latest commits and navigate your code's different branches and tags.

Friday, March 27, 2009

Purge / Delete messages from JMS Weblogic

You can use JMX to purge the queue, either from Java or from WLST (Python). You can find the MBean definitions for WLS. Here is a basic Java program don't forget to put weblogic.jar in the CLASSPATH:

import java.util.Hashtable;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.ObjectName;
import javax.naming.Context;
import weblogic.management.mbeanservers.runtime.RuntimeServiceMBean;
public class PurgeWLSQueue {
    private static final String WLS_USERNAME = "weblogic";
    private static final String WLS_PASSWORD = "weblogic";
    private static final String WLS_HOST = "localhost";
    private static final int WLS_PORT = 7001;
    private static final String JMS_SERVER = "wlsbJMSServer";
    private static final String JMS_DESTINATION = "test.q";

    private static JMXConnector getMBeanServerConnector(String jndiName) throws Exception {
        Hashtable<String,String> h = new Hashtable<String,String>();
        JMXServiceURL serviceURL = new JMXServiceURL("t3", WLS_HOST, WLS_PORT, jndiName);
        h.put(Context.SECURITY_PRINCIPAL, WLS_USERNAME);
        h.put(Context.SECURITY_CREDENTIALS, WLS_PASSWORD);
        h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
        JMXConnector connector = JMXConnectorFactory.connect(serviceURL, h);
        return connector;
    }

    public static void main(String[] args) {
        try {
            JMXConnector connector = getMBeanServerConnector("/jndi/"+RuntimeServiceMBean.MBEANSERVER_JNDI_NAME);
            MBeanServerConnection mbeanServerConnection = connector.getMBeanServerConnection();

            ObjectName service = new ObjectName("com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
            ObjectName serverRuntime = (ObjectName) mbeanServerConnection.getAttribute(service, "ServerRuntime");
            ObjectName jmsRuntime = (ObjectName) mbeanServerConnection.getAttribute(serverRuntime, "JMSRuntime");
            ObjectName[] jmsServers = (ObjectName[]) mbeanServerConnection.getAttribute(jmsRuntime, "JMSServers");
            for (ObjectName jmsServer: jmsServers) {
                if (JMS_SERVER.equals(jmsServer.getKeyProperty("Name"))) {
                    ObjectName[] destinations = (ObjectName[]) mbeanServerConnection.getAttribute(jmsServer, "Destinations");
                    for (ObjectName destination: destinations) {
                        if (destination.getKeyProperty("Name").endsWith("!"+JMS_DESTINATION)) {
                            Object o = mbeanServerConnection.invoke(destination,"deleteMessages",new Object[] {""},// selector expression
                                new String[] {"java.lang.String"});
                            System.out.println("Result: "+o);
                            break;
                        }
                    }
                    break;
                }
            }
            connector.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Above solution works great on a single node environment, but what happens if you are on an clustered environment with ONE migratable JMSServer (currently on node #1) and this code is executing on node #2. Then there will be no JMSServer available and no message will be deleted.Solution:
ObjectName service = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
and be sure to access the admin port on the WLS-cluster.

Here is an example in WLST for a Managed Server running on port 7005:
connect('weblogic', 'weblogic', 't3://localhost:7005')
serverRuntime()
cd('/JMSRuntime/ManagedSrv1.jms/JMSServers/MyAppJMSServer/Destinations/MyAppJMSModule!QueueNameToClear')
cmo.deleteMessages('')
The last command should return the number of messages it deleted.

Monday, January 12, 2009

Removing the 128-bit key restriction in Java

Removing the 128-bit key restriction in Java
An issue in choosing an encryption key size in Java is that by default, current versions of the JDK have a deliberate key size restriction built in. If you try to perform, say, 256-bit AES encryption with the default JDK, you'll find that it dutifully throws an InvalidKeyException, complaining with the not-too-explicit message "Illegal key size or default parameters". If you get this exception, you're probably not doing anything wrong: You've just hit an arbitrary restriction imposed by (at least Sun's) JDK with default settings.

It turns out that the Cipher class will generally not allow encryption with a key size of more than 128 bits. The apparent reason behind this is that some countries (although increasingly fewer) have restrictions on the permitted key strength of imported encryption software, although the actual number 128 is questionable (see below). The good news is that:
You can easily remove the restriction by overriding the security policy files with others that Sun provides.Of course, by "easily", we mean "easy for somebody who doesn't mind downloading a zip, extracting some files from them and copying them to the right place inside the JRE folder". For some customers, this could make deployment a little impractical.

At present, the file you need is called Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6 and is currently available at the Java SE download page. This zip file contains a couple of policy jars, which you need copy over the top of the ones already in the lib/security directory of your JRE.

How to determine if a client has this restrictionYou can use Cipher.getMaxAllowedKeyLength() to return the maximum key length (in bits) permitted for a given algorithm. For example, to find out the maximum permitted key size with AES, we can call:
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
Note that this method generally returns the maximum key length permitted by policy, not necessarily by that algorithm!

Where did the number 128 come from?Now I have to confess, not being a politician, lawyer or lobotomised chimpanzee, I don't fully understand the rationale behind the number 128, for at least two reasons:
  • It's difficult to actually find a reference to any country's current import law that specifically mentions the magic number 128 (see Bert-Jaap Koops' cryptography law survey). 
  • In any case, the JDK ships with a 160-bit secure hash algorithm and a random number generator built on this algorithm. (Remember, you can create a stream cipher by XORing your data with a secure random number source; however strong or weak you argue it is, SecureRandom can in effect serve as a 160-bit encryption algorithm.)

Friday, January 2, 2009

Tuning the compaction and thread local area (TLA) size.

  1. Compaction is used to reduce heap fragmentation, i.e., move objects to form contiguous ‘live regions’ of the heap space. Note when a full compaction is run the stopping of a concurrently running application is inevitable. We can say that compaction is one of the worst garbage collection bottlenecks. If anything is known about fragmentation and object sizes it might be beneficial to tune compaction.
  2. The compaction algorithm divides the heap into a number of equally large parts. Each of these is subject to separate compaction that can stop the world. The default is 4096 parts. When compaction is too disruptive it might help to increase the number of heap parts. When compaction fails to keep up with fragmentation it might help to decrease the number of heap parts. Note that, for strategies other than throughput the compaction areas are sized dynamically.
  3. The proper tuning of compaction involves two parameters:
    1. Compaction ratio (-XX:compaction:percentage:<percentage> or -XX:compaction:internalPercentage=<percentage>,externalPercentage=<percentage>) – the percentage of the heap that the garbage collector compacts at each garbage collection. While the JVM is compacting the heap, all threads that want to access objects need to wait because the JVM is moving the objects around.
    2. Maximum references (-XX:compaction:maxReferences:<value>) – the maximum number of references to objects in the compaction area. If the number of references exceeds this limit, the compaction is canceled. When compaction has moved objects, the references to these objects must be updated. The pause time introduced by this updating is proprotional to the number of references that have been updated.
  4. Steps to tune compaction are as follows:
    1. Set the compaction ratio to 1 and gradually increase the ratio until the pause time becomes too long.
    2. If the garbage collection time is too long when the compaction ration is 1, the maximum number of references must be adjusted.
    3. Set the maximum references to 10000 and gradually increase the references until the pause time becomes too long. To monitor compaction behavior, we can add the option -Xverbose:compaction to the command-line. If many compactions are skipped, the maximum references must be increased; if, on the other hand, the compaction pause times are too long the maximum references must be decreased.
    4. As we are using a dynamic garbage collection that optimizes the pause time (-Xgc:pausetime), we do not need to tune the compaction manually in this case setting the -XpauseTarget is sufficient.
  5. Each thread allocates objects in a TLA that is promoted to the heap when full. The TLA size can be adjusted by using -XXtlaSize:min=<size>,preferred=<size>,wasteLimit=<size>, in which:
    1. min – sets the minimum size of a TLA.
    2. preferred – sets the preferred size of a TLA. The system will try to get TLAs of the preferred size if possible, but accepts TLAs of minimum size as well.
    3. wasteLimit – sets the waste limit for TLAs. This is the maximum amount of free memory that a TLA is allowed to have when a thread requires a new TLA