Fork me on GitHub

linuxaddicted.de

Linux | Dev | Ops

Perl: Use of Flock

This is a small example on flock. It may help you to prevent multiple running instances of the same script. Assume you run the script via cron and it may not be finished when cron attempts to start it again. This few lines of code solve this issue.

flock example
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
if ( ! open( LOCK, ">/var/run/my_app.lock" ) ) {
    print "Failed to open lock file: $!\n";
    exit(1);
}

## Create exclusive, non blocking lock: LOCK_EX(2) + LOCK_NB(4)
if ( ! flock( LOCK, 6 ) ) {
    close( LOCK );

    if ( ! open( PID, "</var/run/my_app.pid" ) ) {

        print "Failed to read PID file: $!\n";
        exit(1);
    }

    my $pid = <PID>;
    close( PID );

    print "Failed to accquire lock. Another instance (PID $pid) running!\n";
    exit(1);
}
else {
    if ( ! open( PID, ">/var/run/my_app.pid" ) ) {

        print "Failed to open pid file: $!\n";
        exit(1);
    }

    print PID $$;

    if ( ! close( PID ) ) {
        print "Failed to write PID file: $!\n";
        exit(1);
    }
}

Useful BASH Setting: Ignore Duplicate Commands

There are many settings that make BASH even more usable. As many people doesn’t seem to know this particular parameter i post it here:

1
HISTCONTROL="ignoredups"

This setting in bashrc or profile makes BASH ignore duplicate commands when searching the history. It’s pretty useful if you had entered the same command several times.

Gentoo: Unmerging Software Including Configs and Data

If you’re unmerging software in Gentoo some files stay on your server. This is a result of the setting CONFIG_PROTECT. To unmerge a package completely use this command:

1
CONFIG_PROTECT="" emerge -C [SOFTWARE]

Qualcomm MSM6275 UMTS Vodafone Card

Preferences

First of all make sure UMTS card is recognized by your system. You need PCMCIA support enabled in your kernel. If you compiled it as modules load the modules.

Device check
1
2
3
4
deathstar ~ # lspci
...
04:00.0 Network controller: Option N.V. Qualcomm MSM6275 UMTS chip
...

Nozomi – card access

Download und build the Nozomi kernel module. You can get it here

Nozomi install
1
2
3
4
5
cd nozomi_2.21alpha_060917
mkdir -p /lib/modules/KERNEL_VERSION/kernel/drivers/pci/hotplug (if it doesn't exists)
make
depmod
modprobe nozomi

After you succeeded in loading the nozomi module you should see something like this in dmesg:

dmesg
1
2
3
4
nozomi 0000:04:00.0: Nozomi driver nozomi_tty
Initializing Nozomi driver 2.21alpha (build date: Jun  9 2008 15:00:29)
nozomi 0000:04:00.0: Version of card: 3
nozomi 0000:04:00.0: Initialization OK!

PPP Configuration

You have to supply the PIN to your SIM-card. There are two ways to accomplish this:

  • Add AT+CPIN=MY_SIM_PIN to your chat script
  • Use a little Perl script (for example if you use a PIN app)
Perl helper
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
#!/usr/bin/perl

use strict;
use warnings;

$SIG{ALRM} = sub { die("timeout: no response from modem $modem\n"); };

my ยงpin   = shift;
my $modem = '/dev/noz0';

open(MODEM, "+<", $modem) or die("Failed to open modem $modem: $!");
print(MODEM "AT+CPIN=\"$pin\"\n\r");
while (<MODEM>) {
    if (m/OK/) {
        close(MODEM);
        print("PIN accepted\n");
        exit(0);
    }
    if (m/ERROR/) {
        close(MODEM);
        print("PIN rejected\n");
        exit(1);
    }
}

exit(0);

Now it’s time to create the PPP config and chat scripts.

/etc/ppp/peers/umts
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Most GPRS phones don't reply to LCP echo's
lcp-echo-failure 0
lcp-echo-interval 0
# Keep pppd attached to the terminal:
# Comment this to get daemon mode pppd
nodetach
# Debug info from pppd:
# Comment this off, if you don't need more info
debug
# Connect script:
# scripts to initialize the UMTS modem and start the connection,
connect /etc/ppp/peers/umts-connect-chat
# Disconnect script:
# AT commands used to 'hangup' the UMTS connection.
disconnect /etc/ppp/peers/umts-disconnect-chat
# Serial device to which the UMTS card is connected:
/dev/noz0
# Serial port line speed
115200
# Hardware flow control:
# Use hardware flow control with cable, Bluetooth and USB but not with IrDA.
crtscts  # serial cable, Bluetooth and USB, on some occations with IrDA too
#nocrtscts # IrDA
# Ignore carrier detect signal from the modem:
local
# IP addresses:
# - accept peers idea of our local address and set address peer as 10.0.0.1
# (any address would do, since IPCP gives 0.0.0.0 to it)
# - if you use the 10. network at home or something and pppd rejects it,
# change the address to something else
0.0.0.0:0.0.0.0
# pppd must not propose any IP address to the peer!
noipdefault
# Accept peers idea of our local address
ipcp-accept-local
# Add the ppp interface as default route to the IP routing table
defaultroute
# DNS servers from the phone:
# some phones support this, some don't.
usepeerdns
# ppp compression:
# ppp compression may be used between the phone and the pppd, but the
# serial connection is usually not the bottleneck in GPRS, so the
# compression is useless (and with some phones need to disabled before
# the LCP negotiations succeed).
novj
nobsdcomp
novjccomp
nopcomp
noaccomp
# The phone is not required to authenticate:
noauth
mtu 1500
mru 1500
/etc/ppp/peers/umts-connect-chat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
exec chat             \
  TIMEOUT   5       \
  ECHO    ON        \
  ABORT   '\nBUSY\r'      \
  ABORT   '\nERROR\r'     \
  ABORT   '\nNO ANSWER\r'     \
  ABORT   '\nNO CARRIER\r'    \
  ABORT   '\nNO DIALTONE\r'   \
  ABORT   '\nRINGING\r\n\r\nRINGING\r'  \
  ''    \rAT        \
  TIMEOUT   12        \
  SAY   "Press CTRL-C to close the connection at any stage!"  \
  SAY   "\ndefining PDP context...\n" \
  OK    ATH       \
  OK    ATE1        \
  OK    'AT+CGDCONT=1,"IP","web.vodafone.de","",0,0'  \
  OK    ATD*99#       \
  TIMEOUT   22        \
  SAY   "\nwaiting for connect...\n"  \
  CONNECT   ""        \
  SAY   "\nConnected." \
  SAY   "\nIf the following ppp negotiations fail,\n" \
  SAY   "try restarting the phone.\n"
/etc/ppp/peers/umts-disconnect-chat
1
2
3
4
5
6
7
8
exec /usr/sbin/chat -V -s -S  \
ABORT   "BUSY"    \
ABORT   "ERROR"   \
ABORT   "NO DIALTONE" \
SAY   "\nSending break to the modem\n"  \
""    "\K"    \
""    "+++ATH"  \
SAY   "\nPDP context detached\n"

Time to go online

Connect
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
40
41
42
43
44
45
46
47
48
49
50
51
52
deathstar ~ # pppd call gprs
Press CTRL-C to close the connection at any stage!
defining PDP context...
AT
OK
ATH
OK
ATE1
OK
AT+CGDCONT=1,"IP","web.vodafone.de","",0,0
OK
waiting for connect...
ATD*99#
CONNECT
Connected.
If the following ppp negotiations fail,
try restarting the phone.
Serial connection established.
using channel 1
Using interface ppp0
Connect: ppp0 <--> /dev/noz0
sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x9aa17e40>]
rcvd [LCP ConfReq id=0x0 <asyncmap 0x0> <auth chap MD5> <magic 0x90ae7a2e> <pcomp> <accomp>]
No auth is possible
sent [LCP ConfRej id=0x0 <auth chap MD5> <pcomp> <accomp>]
rcvd [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x9aa17e40>]
rcvd [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x90ae7a2e>]
sent [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x90ae7a2e>]
sent [CCP ConfReq id=0x1 <deflate 15> <deflate(old#) 15>]
sent [IPCP ConfReq id=0x1 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns3 0.0.0.0>]
rcvd [LCP DiscReq id=0x2 magic=0x90ae7a2e]
rcvd [LCP ProtRej id=0x3 80 fd 01 01 00 0c 1a 04 78 00 18 04 78 00]
rcvd [IPCP ConfNak id=0x1 <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14> <ms-wins 10.11.12.13> <ms-wins 10.11.12.14>]
sent [IPCP ConfReq id=0x2 <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14>]
rcvd [IPCP ConfNak id=0x2 <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14> <ms-wins 10.11.12.13> <ms-wins 10.11.12.14>]
sent [IPCP ConfReq id=0x3 <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14>]
rcvd [IPCP ConfNak id=0x3 <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14> <ms-wins 10.11.12.13> <ms-wins 10.11.12.14>]
sent [IPCP ConfReq id=0x4 <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns3 10.11.12.14>]
rcvd [IPCP ConfReq id=0x0]
sent [IPCP ConfNak id=0x0 <addr 0.0.0.0>]
rcvd [IPCP ConfNak id=0x4 <addr 77.24.36.100> <ms-dns1 139.7.30.125> <ms-dns3 139.7.30.126>]
sent [IPCP ConfReq id=0x5 <addr 77.24.36.100> <ms-dns1 139.7.30.125> <ms-dns3 139.7.30.126>]
rcvd [IPCP ConfAck id=0x5 <addr 77.24.36.100> <ms-dns1 139.7.30.125> <ms-dns3 139.7.30.126>]
rcvd [IPCP ConfReq id=0x1]
sent [IPCP ConfAck id=0x1]
Could not determine remote IP address: defaulting to 10.64.64.64
local  IP address 77.24.36.100
remote IP address 10.64.64.64
primary   DNS address 139.7.30.125
secondary DNS address 139.7.30.126
Script /etc/ppp/ip-up started (pid 8494)
Script /etc/ppp/ip-up finished (pid 8494), status = 0x1

That’s it!

BigIP Client Certificates

This howto will show you how to use client certificates to authenticate against applications hosted by a BigIP loadbalancer. You may find this howto (or parts of it) on ask.f5.com as they was no documentation before on this topic. I forwarded it to F5 some time ago. This is the only way to use client certificates without purchasing addon modules from F5.

Purpose

If you host a website/application which should only be accessible by some users you you may have already thought about client certificates. This makes brute force attacks against login panels impossible. This increases the overall application security by adding another layer a user must pass.

The mapping between certificates and access rights is based on a LDAP directory.

Overview

The loadbalancer reads the CN from the client certificate and searches the defined group for the virtual server for a matching entry. The loadbalancer verifies CA and CRL’s before the lookup takes place.

LDAP Setup

Example LDAP tree
1
2
3
4
5
6
7
8
9
10
dc=company,dc=com
   /         \
  /           \
...      ou=datacenter
           /        \
          /          \
        ...       ou=webauth
                   /    \
                  /      \
            ou=users    ou=groups

User & Group LDIF

Here are two LDIF examples for users and groups:

User LDIF
1
2
3
4
5
dn: cn=Example User,ou=users,ou=webauth,ou=datacenter,dc=company,dc=com
cn: Example User
sn: Example User
objectClass: person
description: It's just a example user
Group LDIF
1
2
3
4
5
6
7
dn: cn=Example Group,ou=groups,ou=webauth,ou=datacenter,dc=company,dc=com
cn: Example Group
objectClass: posixGroup
description: Group is allowed to connect to BigIP's VHOST secure.company.com
memberUid: cn=Example User,ou=users,ou=webauth,ou=datacenter,dc=company,dc=com
memberUid: cn=Example User No2,ou=users,ou=webauth,ou=datacenter,dc=company,dc=com
gidNumber: 145

The “memberUid” has to match exactly the certificates CN because this is the key the BigIP is looking for.

BigIP Configuration

Authentication Configuration

As a first step we create a new “Authentication Configuration”. Just open the web frontend and navigate to:

Local TrafficProfilesAuthenticationConfiguration

You have to create a new config for every virtual host you want to secure. This is force by the LDAP group used because every config can only use one group. Here’s a example configuration:

Authentication Configuration
1
2
3
4
5
6
7
8
9
10
11
12
Parameter        | Value
==========================================================================
Hosts            | 1.2.3.4
Search Type      | User
User Base        | DNou=users,ou=webauth,ou=datacenter,dc=company,dc=com
User Key         | cn
Admin DN         | DN for binding
Admin Password   | Bind password
Group Base DN    | ou=groups,ou=webauth,ou=datacenter,dc=company,dcc=com
Group Key        | cn
Group Member Key | memberUid
Valid Groups     | Corresponding LDAP group

Authentication Profile

The next step is to create a profile which inherits the new created config. You need a profile for every configuration. Navigate to

Local TrafficProfilesAuthenticationProfiles

Authentication Profile
1
2
3
4
5
6
Parameter      | Value
==========================================================================
Type           | SSL Client Certificate LDAP
Parent Profile | ssl_cc_ldap
Mode           | Enabled
Configuration  | NAME OF CONF JUST CREATED

CA Upload

If your CA certificate(s) have not been installed it’s time to do so.

Local TrafficSSL CertificatesImport

SSL Profiles

To use SSL (without client certificates too) you need a SSL profile. Navigate to

Local TrafficProfilesSSLClient

Create a new profile based on “clientssl” or one of your already defined profiles.

SSL Client
1
2
3
4
5
6
7
Parameter                          | Value
==========================================================================
Chain                              | CompanyBundle
Trusted Certificate Authorities    | CompanyBundle
Client Certificate                 | require
Frequency                          | always
Advertised Certificate Authorities | CompanyBundle

Virtual Host Configuration

You may create a new virtual host or modify a existing host. Navigate here

Local TrafficVirtual Servers

Modify the following parameters (if you already used SSL in this vhost):

Virtual Servers
1
2
3
4
Parameter               | Value
==========================================================================
SSL Profile (Client)    | Profile created earlier
Authentication Profiles | Profile created earlier

That’s it!

Import your client certificates to your browser and enjoy your secure connection.

If you have any trouble don’t hesitate to contact me: daniel {A_T} linuxaddicted {D_O_T} de

Postfix Relay Based on OpenLDAP

This howto describes the configuration of a Postfix relay based on OpenLDAP. These are the features of the relay:

  • User verification through LDAP
  • Separation on internal and external users
  • Greylisting
  • User Relaying based on TLS and LDAP authentication
  • Forwarding to local mailserver

HA Linux Router

This howto describes the setup of a HA Linux router based on Gentoo and Keepalived. I’m writing this because there’s not really a good documentation on this topic so far. At least as i searched for it.

Requirements

The intended router requires this config and tools:

  • Kernel with activcated VLAN support(CONFIG_VLAN_8021Q=y)
  • Keepalived installed
  • vconfig installed
  • Optionally bonding support in Kernel and ifenslave installed

Network Configuration

This configuration example is designed for 8 NIC’s and 20 VLAN’s. The following config is split to make it more readable but belongs completely to /etc/conf.d/net.

VLAN-Interface-Mapping

Depending on your network and traffic you have to find a VLAN-interface-mapping that matches your environment.

/etc/conf.d/net - part 1
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
#######################################################
## VLAN <--> Interface Mapping
#######################################################

## eth0: VLAN 20 - 22
vlans_eth0="20 21 22"

## eth1: VLAN 22
vlans_eth1="22"

## eth2: VLAN 23 - 24
vlans_eth2="23 24"

## eth3: VLAN 25 26 27 28
vlans_eth3="25 26 27 28"

## eth4: VLAN 29
vlans_eth4="29"

## eth5: VLAN 30 - 34
vlans_eth5="30 31 32 33 34"

## eth6: VLAN 35 - 38 
vlans_eth6="35 36 37 38"

## eth7: VLAN 39 - 40
vlans_eth7="39 40"

VLAN Settings

This VLAN setup will lead to interfaces named vlanXX. See the manpage of vconfig if you prefer a different setup. Then it’s time to disable the “parent interfaces”. You can’t use a interface in mixed mode: VLAN’s or single interface.

/etc/conf.d/net - part 2
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
#######################################################
## VLAN Interface naming scheme
#######################################################

vconfig_eth0=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth1=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth2=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth3=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth4=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth5=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth6=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
vconfig_eth7=( "set_name_type VLAN_PLUS_VID_NO_PAD" )

#######################################################
## Disable interfaces for "normal" use
#######################################################

config_eth0=( "null" )
config_eth1=( "null" )
config_eth2=( "null" )
config_eth3=( "null" )
config_eth4=( "null" )
config_eth5=( "null" )
config_eth6=( "null" )
config_eth7=( "null" )

IP Adresses

Now it’s time to assign addresses to our VLAN interfaces. I myself prefer the last 3 adresses of every subnet as router addresses.

/etc/conf.d/net - part 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-
-            192.168.45.0/25
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-
- Router-VIP  ==> 192.168.45.254 Cluster IP
- Router-A    ==> 192.168.45.253 Real-IP Node A
- Router-B    ==> 192.168.45.252 Real-IP Node B

config_vlan20=( "10.1.20.0/24" )
config_vlan21=( "10.1.21.0/24" )
config_vlan22=( "10.1.22.0/24" )
config_vlan23=( "10.1.23.0/24" )
config_vlan24=( "10.1.24.0/24" )
config_vlan25=( "10.1.25.0/24" )
config_vlan26=( "10.1.26.0/24" )
config_vlan27=( "10.1.27.0/24" )
config_vlan28=( "10.1.28.0/24" )
config_vlan29=( "10.1.29.0/24" )
config_vlan30=( "10.1.30.0/24" )
...

Routing

If you’re familiar with Gentoo’s routing syntax you shouldn’t be surprised to see how it works.

/etc/conf.d/net - part 4
1
2
routes_vlan21=("192.168.99.0/27 via 10.1.21.5")
routes_vlan31=("default via 10.1.31.1")

Keepalived Configuration

/etc/keepalived/keepalived.conf - MASTER
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## Unique identifier for every router
global_defs {
   router_id router-a
}

## Sync Group
vrrp_sync_group SG_A {
  group {
          VI_21 # VLAN 21
          VI_22 # VLAN 22
          VI_23 # VLAN 23
          VI_24 # VLAN 24
          VI_25 # VLAN 25
          VI_26 # VLAN 26
          VI_27 # VLAN 27
          VI_28 # VLAN 28
          VI_29 # VLAN 29
          VI_30 # VLAN 30
          VI_31 # VLAN 31

          ...
        }
}

## VLAN 21
vrrp_instance VI_21 {
    interface vlan21
    state MASTER
    virtual_router_id 21
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass >FreakShow_<
    }
    virtual_ipaddress {
        10.1.21.254
    }
}

## VLAN 22
vrrp_instance VI_22 {
    interface vlan22
    state MASTER
    virtual_router_id 22
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass >FreakShow_<
    }
    virtual_ipaddress {
        10.1.22.254
    }
}

...
/etc/keepalived/keepalived.conf - SLAVE
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## Unique identifier for every router
global_defs {
   router_id router-b
}

## Sync Group
vrrp_sync_group SG_B {
  group {
          VI_21 # VLAN 21
          VI_22 # VLAN 22
          VI_23 # VLAN 23
          VI_24 # VLAN 24
          VI_25 # VLAN 25
          VI_26 # VLAN 26
          VI_27 # VLAN 27
          VI_28 # VLAN 28
          VI_29 # VLAN 29
          VI_30 # VLAN 30
          VI_31 # VLAN 31

          ...
        }
}

## VLAN 21
vrrp_instance VI_21 {
    interface vlan21
    state SLAVE
    virtual_router_id 21
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass >FreakShow_<
    }
    virtual_ipaddress {
        10.1.21.254
    }
}

## VLAN 22
vrrp_instance VI_22 {
    interface vlan22
    state SLAVE
    virtual_router_id 22
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass >FreakShow_<
    }
    virtual_ipaddress {
        10.1.22.254
    }
}

...