The easiest way to install on Solaris is to obtain the packages from http://OpenCSW.org. OpenCSW uses a tool called pkgutil on top of the existing Solaris toolset to obtain, install and maintain OpenCSW packages.
Configuring Transitive IPMP on Solaris 11
We all know the pain of configuring probe-based IPMP under Solaris, with a slew of test addresses being required, and a long line of ifconfig configuration in our /etc/hostname.<interface> files.
With Solaris 11, there is a new type of probe-based IPMP called transitive probing. This new type of probing does not require test addresses, as per the documentation: “Transitive probes are sent by the alternate interfaces in the group to probe the active interface. An alternate interface is an underlying interface that does not actively receive any inbound IP packets”.
In this article, I will configure failover (active/passive) IPMP on clusternode1 (the first node of a Solaris Cluster I’m building). Interface net0 has an address of 10.1.1.80 (configured at install time), and I’ll be adding this into an IPMP group ipmp0 along with a standby interface, net1. Make sure you are performing these steps via a console connection, as the original address associated with net0 will need to be removed before attempting to add it to an IPMP group.
The first step, ensure that there is an entry in /etc/hosts for the IP address you’re configuring IPMP for:
|
1 2 |
# grep '^10\.1\.1\.80' /etc/hosts 10.1.1.80 clusternode1 |
Next, ensure that automatic network configuration is disabled. In my case it was as I’d configured networking manually during the installation of Solaris 11:
|
1 2 3 4 |
# netadm list -p ncp -x TYPE PROFILE STATE AUXILIARY STATE ncp Automatic disabled disabled by administrator ncp DefaultFixed online active |
Verify that the appropriate physical interfaces are available. In the following output, I’ll be bonding e1000g0 (net0) and e1000g1 (net1) into a failover IPMP group.
|
1 2 3 4 5 6 |
# dladm show-phys LINK MEDIA STATE SPEED DUPLEX DEVICE net1 Ethernet unknown 0 unknown e1000g1 net2 Ethernet unknown 0 unknown e1000g2 net3 Ethernet unknown 0 unknown e1000g3 net0 Ethernet up 1000 full e1000g0 |
List the current addresses - from the output of ipadm show-addr I can see that I’ll need to delete net0/v4 and net0/v6, otherwise I’ll be unable to add net0 to the IPMP group.
|
1 2 |
# ipadm delete-addr net0/v4 # ipadm delete-addr net0/v6 |
As the net0 IP interface is already created, I only need to create the net1 interface:
|
1 |
# ipadm create-ip net1 |
I can then create the IPMP group, which I’ll call ipmp0:
|
1 |
# ipadm add-ipmp -i net0 -i net1 ipmp0 |
Next, enable transitive probing, which is disabled by default:
|
1 2 3 4 |
# svccfg -s svc:/network/ipmp setprop config/transitive-probing=true # svccfg -s svc:/network/ipmp listprop config/transitive-probing config/transitive-probing boolean true # svcadm refresh svc:/network/ipmp:default |
And configure the appropriate interface (in my case net1) to be a standby interface (as I’m using failover):
|
1 |
# ipadm set-ifprop -p standby=on -m ip net1 |
Now I can create my IPv4 address on the IPMP group:
|
1 2 3 4 |
# ipadm create-addr -T static -a clusternode1/24 ipmp0/v4 # ipadm show-addr ipmp0 ADDROBJ TYPE STATE ADDR ipmp0/v4 static ok 10.1.1.80/24 |
Finally, fix the default route. I removed the existing route and added a new default route using the new and correct interface - ipmp0:
|
1 2 3 4 5 6 7 8 9 10 |
# route -p delete default 10.1.1.1 # route -p add default 10.1.1.1 -ifp ipmp0 # netstat -rn -f inet Routing Table: IPv4 Destination Gateway Flags Ref Use Interface -------------------- -------------------- ----- ----- ---------- --------- default 10.1.1.1 UG 1 0 ipmp0 10.1.1.0 10.1.1.80 U 8 388 ipmp0 127.0.0.1 127.0.0.1 UH 2 554 lo0 |
You can use ipmpstat to verify the configuration and health of the IPMP group:
|
1 2 3 4 5 6 7 8 9 10 11 |
# ipmpstat -g GROUP GROUPNAME STATE FDT INTERFACES ipmp0 ipmp0 ok 10.00s net0 (net1) # ipmpstat -a ADDRESS STATE GROUP INBOUND OUTBOUND :: down ipmp0 -- -- clusternode1 up ipmp0 net0 net0 # ipmpstat -t INTERFACE MODE TESTADDR TARGETS net1 transitive <net1> <net0> net0 routes clusternode1 10.1.1.1 |
Let’s perform a failover test. I’ll disable net0 and ensure that the clusternode1 address fails over:
|
1 2 3 4 |
# ipadm disable-if -t net0 # ipmpstat -t INTERFACE MODE TESTADDR TARGETS net1 routes clusternode1 10.1.1.1 |
It works! (and my SSH connection is still active…) - net1 is now active with the correct IP address. Let’s fail it back:
|
1 2 3 4 5 |
# ipadm enable-if -t net0 # ipmpstat -t INTERFACE MODE TESTADDR TARGETS net0 routes clusternode1 10.1.1.1 net1 transitive <net1> <net0> |
The address has failed back to net0, and again my SSH connection is still active. I can now continue with clusternode2, and the rest of the cluster install.
Adding Logging to IPTables under CentOS
Whilst troubleshooting some firewall issues with a CentOS host, I wanted to enable logging. Thankfully, there is a very customisable iptables target - LOG (funnily enough) - that will do this in a few steps.
First, add a new chain with a reasonable name. I chose LOGGING:
|
1 |
# iptables -N LOGGING |
Next, review the current iptables configuration to ensure that the chain has been created successfully:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# iptables -L -n --line-numbers Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 5 ACCEPT udp -- 192.168.122.0/24 0.0.0.0/0 state NEW udp dpt:53 6 ACCEPT tcp -- 192.168.122.0/24 0.0.0.0/0 state NEW tcp dpt:53 7 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) num target prot opt source destination 1 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) num target prot opt source destination Chain LOGGING (0 references) num target prot opt source destination |
Next, insert a rule at the appropriate point (hence me using --line-numbers above). You could replace the existing REJECT at line 7 in its entirety as its functionality will be moved into the LOGGING chain (where I change it to a DROP anyway):
|
1 |
# iptables -I INPUT 7 -j LOGGING |
Add the actual logging rule next. I also use the limit module to add some rate-limiting into the mix. The iptables man page documents both the LOG target and the limit module in great detail. But - here I specify a limit of 10 messages per minute, which is ample for my testing. The log level is set at debug (as per standard syslog log levels).
|
1 |
# iptables -A LOGGING -m limit --limit 10/min -j LOG --log-prefix "DROP: " --log-level 7 |
Finally, we actually DROP the packet (whether it has been logged, or not (if the rate limit has been exceeded)):
|
1 |
# iptables -A LOGGING -j DROP |
OK - let’s check our iptables configuration once again:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 ACCEPT udp -- 192.168.122.0/24 0.0.0.0/0 state NEW udp dpt:53 ACCEPT tcp -- 192.168.122.0/24 0.0.0.0/0 state NEW tcp dpt:53 LOGGING all -- 0.0.0.0/0 0.0.0.0/0 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain LOGGING (1 references) target prot opt source destination LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 10/min burst 5 LOG flags 0 level 7 prefix `DROP: ' DROP all -- 0.0.0.0/0 0.0.0.0/0 |
Everything looks good. Try telnetting to a bad port, or doing something else the firewall should block, and depending upon your syslog configuration, the DROP message should be logged, for example:
|
1 |
May 20 21:40:42 somehost kernel: DROP: IN=eth0 OUT= MAC=DE:AD:BE:EF:8d:b2:52:54:00:ff:d4:30:08:00 SRC=192.168.122.1 DST=192.168.122.10 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=19162 DF PROTO=TCP SPT=38141 DPT=54 WINDOW=14600 RES=0x00 SYN URGP=0 |
If nothing is broken, save your configuration:
|
1 |
# service iptables save |
As an aside, if (as with the default rsyslog configuration under CentOS 6.x) nothing is logged, you will need to configure rsyslog appropriately. We specified a --log-level of 7 - which is the debug syslog log level. So we need to configure rsyslog to send messages from the kern facility at log level 7 to somewhere useful. I chose /var/log/firewall.log:
|
1 2 3 4 5 |
# vi /etc/rsyslog.conf ... kern.debug /var/log/firewall.log ... # service rsyslog restart |
As a final tidy up, don’t forget to update your logrotate configuration, if required:
|
1 2 3 |
# cd /etc/logrotate.d # vi syslog add /var/log/firewall.log to list of filenames |
Configuring Interface Bonding on CentOS/RHEL/OEL 6.x
In my previous article I wrote about configuring configuring network interface bonding under Debian Wheezy. Here, I’ll briefly outline the steps required to get the same configuration running under recent RHEL-flavoured distributions - namely CentOS 6.4 in my case.
I will be bonding eth0 and eth1 into a bond named bond0. Ensure that you’re connected to your host via a console. I’ll be using active-backup (i.e. failover) bonding, but there are other options available - see the Debian article for links to reference material for those.
First, create the ifcfg-bond0 configuration file:
|
1 2 3 4 5 6 7 8 9 10 |
# cd /etc/sysconfig/network-scripts # vi ifcfg-bond0 DEVICE=bond0 IPADDR=192.168.122.12 NETMASK=255.255.255.0 GATEWAY=192.168.122.1 NM_CONTROLLED=no BOOTPROTO=none ONBOOT=yes USERCTL=no |
Substitute relevant values as appropriate for your setup. Next, edit/create the ifcfg-eth{0,1} files. Note that these are created as slave interfaces (SLAVE=yes) with bond0 as the master interface (MASTER=bond0):
|
1 2 3 4 5 6 7 8 9 |
# vi ifcfg-eth0 DEVICE=eth0 USERCTL=no ONBOOT=yes NM_CONTROLLED=no MASTER=bond0 SLAVE=yes BOOTPROTO=none # sed 's/eth0/eth1/' ifcfg-eth0 > ifcfg-eth1 |
Note - that if NM_CONTROLLED is set, you should strictly define your HWADDR entries too at this step, for each interface. Configure the bonding module. miimon is the MII link monitoring frequency in milliseconds, {down,up}delay are the times, in milliseconds, to wait before disabling or enabling an interface in the bond (to safeguard against flapping), and should be a multiple of the miimon value. Note that /etc/modprobe.conf is deprecated in CentOS 6.x so an appropriate file should be created under /etc/modprobe.d - in our case, bonding.conf:
|
1 2 3 |
# vi /etc/modprobe.d/bonding.conf alias bond0 bonding options bond0 mode=active-backup miimon=100 downdelay=200 updelay=200 |
To test, manually load the module (and appropriate options - I see many tutorials with a simple modprobe bonding here - you’ll end up with the default bonding mode which is round-robin - not what we want):
|
1 |
# modprobe bonding mode=active-backup miimon=100 downdelay=200 updelay=200 |
And restart networking:
|
1 |
# service network restart |
Verify that all is well with ifconfig -a, or more suitably a cat on /proc/net/bonding/bond0:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# cat /proc/net/bonding/bond0 Ethernet Channel Bonding Driver: v3.6.0 (September 26, 2009) Bonding Mode: fault-tolerance (active-backup) Primary Slave: None Currently Active Slave: eth0 MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 200 Down Delay (ms): 200 Slave Interface: eth0 MII Status: up Speed: Unknown Duplex: Unknown Link Failure Count: 0 Permanent HW addr: 52:54:00:c1:77:fc Slave queue ID: 0 Slave Interface: eth1 MII Status: up Speed: 100 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: 52:54:00:f3:11:1e Slave queue ID: 0 |
Reboot the host at the earliest opportunity to verify that all is well after a reboot.
BIND 10: Upgrading from 1.0.0-rc to 1.0.0 - The Production Release
After many years in development, and many releases (development, alpha, beta, release candidate), ISC have announced the final Production release of BIND 10 1.0.0. My previous article covered the upgrade from 1.0.0-beta to 1.0.0-rc. Aside from a database upgrade (which was clearly logged for our attention) the upgrade was very straightforward.
Let’s see if the upgrade from 1.0.0-rc to 1.0.0 is as easy.
Shells: ksh Tab Completion
If you are using the public domain version of the Korn Shell (pdksh), you can add the following line to your .kshrc and (providing ENV is set), you will have tab completion in vi mode:
|
1 |
set -o vi-tabcomplete |
You can see which shell options are currently set by running:
|
1 |
set -o |
Please note, vi-tabcomplete is an option within the public domain Korn Shell only, and will not work with the “standard” ksh provided by many OS’s. In this case, you’ll have to make do with Esc-\ for filename completion.
Securing and Hardening the Linux Operating System
Any application is only as secure as the operating system hosting it. Whilst most servers are protected behind firewalls with the main avenue of exploit being the application, if an application is exploited and the user did manage to obtain server access, we need to minimise the damage that can be done to the exploited machine and others. Running hardened systems is a requirement of certain data security standards such as PCI-DSS (PCI Application Data Security Standard), as well as mandated by many organisations. Plus, it is just good practice. Out-of-the-box, most modern OSes are configured to be secure. There is still a great deal we can do, however, to further harden the operating system to various vectors of attack.
This article will only cover the core aspects of Linux OS lockdown, and will focus on CentOS 6.4. Most of the concepts here should be able to be ported to other flavours, using the appropriate commands for your OS.
For further detail, consult the security benchmarks available at http://cisecurity.org. You should employ multiple layers of security within your architecture – for example, using network-based firewalls as well as host firewalls, writing secure code, ensuring that all aspects of the application stack are patched and up-to-date, etc. Hardening the OS is just one more layer of security.
How to Check md5sum on Solaris 10
If you don’t have the md5sum utility installed, just use the digest tool supplied with Solaris 10
|
1 2 |
$ digest -a md5 -v /bin/ls md5 (/bin/ls) = b57e173220af4b919f1d4bef9db11482 |
BIND 10: How to Upgrade from 1.0.0-beta to 1.0.0-rc
Today, the first RC of BIND 10 was released. There are some new features that will change how you use my previous articles on this subject. Apart from a slew of bug fixes, there are some functionality changes that will affect both the installation and configuration of BIND 10. The BIND 10 Guide has also been updated to reflect these changes.
The major change of note is:
|
1 2 3 4 5 6 7 8 9 10 |
565. [func]* jelte The main initializer script (formerly known as either 'bind10', 'boss', or 'bob'), has been renamed to b10-init (and Init in configuration). Configuring which components are run is henceforth done through '/Init/components', and the sbin/bind10 script is now simply a shellscript that runs b10-init. Existing configuration is automatically updated. NOTE: once configuration with this update has been saved (by committing any new change with bindctl), you cannot run older versions of BIND 10 anymore with this configuration. (Trac #1901, git bae3798603affdb276f370c1ac6b33b011a5ed4f) |
The previous versions of BIND 10 (I was using 1.0.0-beta previously) would have a master process - bind10. This Boss process was responsible for managing the state of other modules, restarting them when they fail, and so on. bind10 is now a shell script that fires up b10-init. This keeps the module names consistent, and we can now address the module as Init. Thus, a Boss shutdown now becomes Init shutdown, Boss show_processlist becomes Init show_processlist, config add /Boss/components b10-auth is now config add /Init/components b10-auth, and so on.
Puppet Module: security::tcpwrappers with Hiera
Module: security::tcpwrappers
Purpose: This module configures TCP Wrappers on CentOS 6 and Solaris 10 hosts with Hiera.
Notes: This module does some pretty fancy things. It uses Hiera to provide lookup for the $hostsallow and $hostsdeny variables, and interfaces with inetadm and svccfg on Solaris. Let’s look at hiera.yaml first.
File: /etc/puppet/hiera.yaml
|
1 2 3 4 5 6 7 8 9 |
--- :backends: - yaml :yaml: :datadir: /etc/puppet/hieradata :hierarchy: - %{::clientcert} - %{::operatingsystem} - common |
As you can see, we first check the %{::clientcert}, then the %{::operatingsystem} before falling back to common. So, essentially you have hostname-specific control if you need it.
Under /etc/puppet/hieradata, I have the following:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@centosa hieradata]# cat centosa.local.yaml --- security::tcpwrappers::hostsallow: "puppet:///modules/security/etc/hosts.allow-centosa.local" security::tcpwrappers::hostsdeny: "puppet:///modules/security/etc/hosts.deny-centosa.local" [root@centosa hieradata]# cat common.yaml --- security::tcpwrappers::hostsallow: "puppet:///modules/security/etc/hosts.allow-common" security::tcpwrappers::hostsdeny: "puppet:///modules/security/etc/hosts.deny-common" [root@centosa hieradata]# cat Solaris.yaml --- security::tcpwrappers::hostsallow: "puppet:///modules/security/etc/hosts.allow-solaris" security::tcpwrappers::hostsdeny: "puppet:///modules/security/etc/hosts.deny-solaris" |
Host centosa.local would use centosa.local.yaml (due to %{::clientcert} in the hierarchy) and pull the values in for security::tcpwrappers::hostsallow and security::tcpwrappers::hostsdeny from that file. Host centosb.local would fall through to common.yaml (unless there was a %{::clientcert}.yaml or Centos.yaml), and a Solaris host would use Solaris.yaml.
File: security/manifests/tcpwrappers.pp
Notes: Uses Hiera to copy in appropriate files. On Solaris, it configures inetd-controlled services to use TCP Wrappers via inetadm, and enables TCP Wrappers for the RPC portmapping service via svccfg.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# class security::tcpwrappers # Set up tcpwrappers on Solaris and CentOS hosts class security::tcpwrappers ( $hostsallow = "", $hostsdeny = "" ) { file { '/etc/hosts.allow' : owner => 'root', group => 'root', mode => '0644', source => $hostsallow } file { '/etc/hosts.deny' : owner => 'root', group => 'root', mode => '0644', source => $hostsdeny } case $::operatingsystem { 'CentOS' : { # nothing else to do, files are in place } 'Solaris' : { # set up inetd-controlled services for tcp_wrappers exec { '/usr/sbin/inetadm -M tcp_wrappers=TRUE' : unless => '/usr/sbin/inetadm -p | /bin/grep tcp_wrappers=TRUE' } # enable TCP wrappers for RPC portmapping service exec { '/usr/sbin/svccfg -s svc:/network/rpc/bind setprop config/enable_tcpwrappers=true' : unless => '/usr/sbin/svccfg -s svc:/network/rpc/bind listprop config/enable_tcpwrappers | /bin/grep true', notify => Service['svc:/network/rpc/bind'] } # need the service defined here so we can notify it service { 'svc:/network/rpc/bind' : ensure => running, enable => true } } default : { fail( 'OS unsupported by security::tcp_wrappers class' ) } } } |