CS IP Filtering: testing the rules

To see all my blog posts on IP filtering see here.

To test the filtering rules you can using the traffic test option of the Unix ipsec -t command.

You need to explicitly give the IP addresses such as 10.1.0.2. Using a subnet 10.1.0.2/24 or other ways, does not work.

The icmp syntax is

For my laptop with address 10.1.0.2 to z/OS on 10.1.1.2

ipsec -t 10.1.0.2 10.1.1.2 icmp -p tcpip > a

You cannot specify the icmp type.

This gave a lot of information, most of which is not very interesting , for example

FilterName:                   icmpinspecific 
FilterNameExtension: n/a
GroupName: n/a
LocalStartActionName: n/a
VpnActionName: n/a
TunnelID: 0x00
Type: Generic
DefensiveType: n/a
State: Active
Action: Permit
Scope: Local
Direction: Inbound
OnDemand: n/a
....

Using the ISPF macro na (below) this removes boring information, and gave for each rule

FilterName:                   icmpinspecific 
Type: Generic
Action: Permit
Direction: Inbound
Logging: All
Protocol: ICMP(1)
ICMPType: 8
SourceAddress: 10.1.0.2
DestAddress: 0.0.0.0
DestAddressPrefix: 0
DiscardAction: Silent

Searching for ICMPType this gave one record with 8 and two with All.

Note: DestAddress: 0.0.0.0 and DestAddressPrefix: 0 means that IpDestAddr was not specified in the rule.

You also need to check the return route exists from z/OS to the laptop

ipsec -t 10.1.1.2 10.1.0.2 icmp -p tcpip > a

The TCP/IP syntax is

ipsec -t 10.1.0.2 10.1.1.2 tcp 4000 443 -p tcpip > a

This is for a web server request from address 10.1.0.2 port 4000 to port 443 on address 10.1.1.2. Port 443 is the “well known (to my users) ” port for the web server. The web clients IP port is allocated by TCP – usually the first available free port.

It displays 3 records

FilterName:                   Colin443 
...
FilterName: DenyAllRule_Generated___________Inbnd
...
FilterName: DenyAllRule_Generated___________Outbnd
...

Where Colin443 is the rule I wrote.

Using the ISPF macro na (below) this removes boring information and leaves

FilterName:                   Colin443 
Type: Generic
Action: Permit
Direction: Inbound
Logging: None
Protocol: TCP(6)
SourceAddress: 10.1.0.2
SourcePort: All
DestAddress: 10.1.1.2
DestPort: 443
DiscardAction: Silent

For my web server to work I also need to have the reverse path from 10.1.1.2 port 443 to 10.1.0.2 port 4000.

ipsec -t 10.1.1.2 10.1.0.2 tcp 443 4000 -p tcpip >a
FilterName:                   Out443 
Type: Generic
Action: Permit
Direction: Outbound
Logging: All
Protocol: TCP(6)
SourceAddress: 10.1.1.2
SourcePort: 443
DestAddress: 10.1.0.2
DestPort: All
DiscardAction: Silent

ISPF macro na

This ISPF macro removes irrelevant information such as all the lines with not-applicable (“n/a”), and only the fields I thought important; FilterName: xtension:….

This macro needs to be put in a clist/rexx library. For example use the tso ISRDDN command, and look for DDNAME SYSPROC. This has a list of “clist” datasets which are available to you.

/* REXX */ 
/* macro to display only interesting field from ipsec command
*/
ADDRESS ISPEXEC
'ISREDIT MACRO'
trace o
"ISREDIT exclude all "
"ISREDIT find 'n/a' all"
"ISREDIT delete all nx "
"ISREDIT reset "
/* only display these fields */
w = "FilterName: xtension: Type Action Direction",
"Logging Protocol Address Port ******"
"ISREDIT exclude all "
do i = 1 to words(w)
"ISREDIT find '"word(w,i)"' all"
end
"ISREDIT delete all x "
"ISREDIT reset "

CS IP filtering: specifying IP addresses to Policy Agent

To see all my blog posts on IP filtering see here.

Within an IpFilterRule you specify IP addresses of the source and destination, for example

IpFilterRule GroupPort443 
{
IpSourceAddr 10.1.0.2
IpSourceAddr 10.1.0.0-10.1.0.8
IpDestAddrGroupRef zGroup
IpGenericFilterActionRef permit
IpService
{
Protocol Tcp
SourcePortRange 443
Direction inbound
Routing local
}
}

You can specify, using IpSource… or IpDest…

  • a single IP address using
    • inline
      • IpFilterRule … { IpSourceAddr 10.1.0.2 … }
    • as a reference to an out of line definition
      • IpSourceAddrRef name1 -> IpAddr name1 {Addr 10.1.0.2}
  • as a subnet using
    • inline
      • IpFilterRule … { IpSourceAddr 10.1.0.2/24 … }
    • as a reference to an out of line definition
      • IpSourceSetRef name2 -> IpAddrSet name2 {Prefix 10.1.0.224}
  • as a range using
    • as a reference to an out of line definition
      • IpSourceSetRef name3 -> IpAddrSet name3 {Range 10.1.0.2-10.1.0.6}
  • as a group, or collection of IP addresss
    • as a reference to out of line definition
      • IpSourceSetRef name4 -> IpAddrGroup name4 {inline IpAddr, IpAddr reference , Inline IpAddrSet, IP Address Setreference…}

An example of three host IP addresses in the common file is:

IpAddrGroup  zGroup 
{
IpAddr
{
Addr 10.1.0.2 ZOSA
}
IpAddr
{
Addr 10.1.0.3 ZOSB
}
IpAddr
{
Addr 10.1.0.4 ZOSC
}
}

Where the ZOSA, ZOSB, ZOSC are treated as comments because they come after the attribute-value.

This is used in the TCPIP instance configuration

IpFilterRule Group443 
{
IpSourceAddr 10.1.0.2
IpDestAddrGroupRef zGroup
IpGenericFilterActionRef permit
IpService ...

You cannot define a group in the TCPIP instance configuration file, it has to be in the

CommonIpSecConfig  //'USER.Z24C.TCPPARMS(PAGEICOM)'

of the Policy Agent Configuration file.

CS IP filtering: adding default rules

To see all my blog posts on IP filtering see here.

You can use the IP filtering component of z/OS Communications Server to allow or deny packets through a TCPIP stack.

You can define

  • Default rules to allow traffic, in TCPIP Profile.
  • Named rules using Policy agent. These can allow or deny access.
  • Dynamic rules which can be automated, for example external monitors, using DMD.

Define default rules

You can define default rules in the startup TCPIP profile – or replace them using an OBEYFILE

IPSEC LOGENable 
; Rule SourceIp DestIp Logging      Prot SrcPort   DestPort ...
  IPSECRULE 10.1.0.2 * LOG Protocol icmp Type 8 
  IPSECRULE * 10.1.0.2   LOG Protocol icmp 
ENDIPSEC 

This enables the default rules. It allow only

  • Ping traffic (icmp type 8) from 10.1.0.2 to any address
  • Any icmp from any address to 10.1.0.2. Note the response to ping is icmp type 0

Any other requests are denied.

A rule SYSDEFAULTDENYRULE is automatically defined. This denies all packets which are not covered by other rules. If you want to log the action of this rule you need

IPSEC LOGENable LOGIMPLICIT

This logs an event like

EZD0815I Packet denied by policy: 11/21/2023 17:11:34.71 
filter rule= SYSDEFAULTDENYRULE ext= 2 
sipaddr= 10.1.0.2 dipaddr= 10.1.1.2 proto= icmp(1) type= 8 code= 0 -= 
Interface= 10.1.1.2 (I) secclass= 255 dest= local len= 84 
vpnaction= N/A tunnelID= N/A ifcname= ETH1 fragment= N 

This could produce a lot of output. NOLOGIMPLICT means do not log packets denied by this rule.

When setting this up for the first time you might want to use

IPSEC LOGENable LOGIMPLICIT
IPSECRULE * *    NOLOG Protocol * 

Then build up rules such as

IPSECRULE 10.1.0.0/24 *    LOG Protocol * 

With this you will get messages in the syslogd file, you can then build up rules to cover the valid cases – then change LOG to NOLOG

If you use the OBEYFILE, the file contents replace any existing IPSEC default. So to add or remove an entry; edit the file, and use OBEYFILE to activate it.

Display the rules using

ipsec -f display -p TCPIP -c profile

The trace record looks like

EZD0814I Packet permitted: 11/18/2023 19:00:42.59 filter 
rule=SYSDEFAULTRULE.1 ext= 2 sipaddr= 10.1.0.2 dipaddr= 10.1.1.2 
proto= icmp(1) type= 8 code= 0 -= Interface= 10.1.1.2 (I) 
secclass= 255 dest= local len= 84 vpnaction= N/A 
tunnelID= N/A ifcname= ETH1 fragment= N 

Observations on the default rules

Some of the definitions seem strange to me!

Using

IPSECRULE 10.1.0.2 10.1.1.2 LOG Protocol icmp direction inbound
IPSECRULE 10.1.1.2 10.1.0.2 LOG Protocol icmp direction outbound

This works as I expect, it allows an inbound icmp request from 10.1.0.2(my laptop) to 10.1.1.2 ( z/OS), and an outbound request from z/OS to my laptop.

If I display the rules using ipsec -f display -p TCPIP

I get

FilterName:              SYSDEFAULTRULE.1
FilterNameExtension:     1
Direction:               Inbound
Logging:                 All
Protocol:                ICMP(1)
SourceAddress:           10.1.0.2
DestAddress:            10.1.1.2

and

FilterName:   SYSDEFAULTRULE.2
Direction: Outbound
Protocol: ICMP(1)
OSPFType: n/a
TCPQualifier: n/a
ProtocolGranularity: n/a
SourceAddress: 10.1.1.2
DestAddress: 10.1.0.2

See Using Direction bidirectional drove me crazy if you were thinking of using direction bidirectional.

CS IP Filtering : use of DiscardAction to send an icmp response back

To see all my blog posts on IP filtering see here.

With IP filtering you can have an action which sends back a negative response to an ICMP request – rather that silently dropping the packet.

The documentation says

ImplicitDiscardAction
Indicates the discard action that is to be applied to packets that are denied by the implicit deny all rule at the end of the filter table. If a packet does not match any of the filter rules defined in Policy Agent, then the packet is denied by an implicit deny all rule.

  • Silent: Specify this value to discard the packet silently.
  • ICMP: Specify this value to send an ICMP or ICMPv6 destination unreachable error with reason administratively prohibited to the origin of the discarded packet. ICMP errors are not generated for locally originated traffic; they are generated only for remote traffic that is being received or forwarded.

For example

IpGenericFilterAction denyit 
{
IpFilterAction deny
DiscardAction ICMP
IpFilterLogging yes
}
# input rule
IpFilterRule icmpinall
{
IpSourceAddr 10.1.0.0/24
IpDestAddr 10.1.1.2
IpGenericFilterActionRef denyit
IpService
{
Protocol icmp
Direction inbound
Routing local
}
}

# Need a rule to allow the traffic to go out
IpFilterRule icmpout
{
IpSourceAddr 10.1.1.2
IpDestAddr 10.1.0.0/24
IpGenericFilterActionRef permit
IpService
{
Protocol icmp
Direction outbound
Routing local
}
}
# Action for outbound ICMP packets
IpGenericFilterAction permit
{
IpFilterAction permit
IpFilterLogging yes
}

Output

If the action is silent, then ping gives

ping 10.1.1.2 
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
^C
--- 10.1.1.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2035ms

if the action is ICMP the output is

colinpaice@colinpaice:~$ ping 10.1.1.2 
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
From 10.1.1.2 icmp_seq=1 Packet filtered
From 10.1.1.2 icmp_seq=2 Packet filtered
^C
--- 10.1.1.2 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms

A wireshark trace of the response is

Internet Control Message Protocol
Type: 3 (Destination unreachable)
Code: 13 (Communication administratively filtered)
  • Type 3 is Destination Unreachable.
  • Code 13 is Communication Administratively Prohibited

CS IP filtering: defining rules with Policy Agent and avoiding the elephant traps

To see all my blog posts on IP filtering see here.

Topics in this post.

It is easy to make your TCPIP instance totally inaccessible.

There are various criteria, such as source IP address, and destination IP Address and port which can be used in the IP filtering rules. The rules are scanned to see if the rule is applicable for the criteria.

  • If the criteria matches, and the action is deny the final result is denied, and the other rules are skipped.
  • If no rule matches then the system generated DenyAllRule_Generated rule is used.

This means if you get your definitions slightly wrong – you may deny all traffic – and so be unable to logon to TSO to fix the definition. You would have to logon to TSO without using TCPIP.

If you only have access to TSO through TCPIP, you need to restart TCPIP with a parameter file with an IPCONFIG file which does not specify IPSECURITY; or use a TCPIP V6 address. Make sure you have a fall back plan as this will cause you an outage.

No syntax checking before activating

I have not found a way of getting the syntax checked except at deploy time. You make your change to the Policy Agent configuration, and issue the refresh command. If there are any errors you get a message

EZZ8438I PAGENT POLICY DEFINITIONS CONTAIN ERRORS FOR TCPIP : IPSEC

and you need to look in the syslogd output for the policy agent (for me in /var/log). Search for OBJERR and WARNING. You can get messages like

WARNING: No ‘IpFilterPolicy’ policy object found in config

Which means you had an error in your configuration, and it was all ignored.

You can display what is current using a command like

ipsec -f display -c current -p TCPIP > a

or

pasearch -a -e -v f -f Colin443 > a

which displays the policy information for ip filtering (-v f) and policy Colin443 (-f Colin443).

I found the output is not very clear. The pasearch command does give information like

Policy created: Wed Dec 6 10:16:06 2023
Policy updated: Wed Dec 6 10:32:50 2023

so you can see when it was last updated in TCPIP (and if your update was made successfully).

Getting the layout correct

It took me a good half day to find a layout error

IpGenericFilterAction denyit 
{
IpFilterAction deny DiscardAction ICMP
IpFilterLogging yes
}

This ignores the DiscardAction ICMP, because you must have only one attribute and its values on each line. The remainder of the line (DiscardAction ICMP) is ignored.

The correct way of doing it is

IpGenericFilterAction denyit 
{
IpFilterAction deny
DiscardAction ICMP
IpFilterLogging yes
}

How do I specify an IP address.?

You can specify an individual address, or a group of addresses, in a variety of slightly different ways. You have to specify the dotted IP address, you cannot specify names.

“inline”

You can specify

IpSourceAddr 10.1.0.2
IpSourceAddr 10.1.0.0/24
IpSourceAddr 10.1.0.0-10.1.0.8

The first line defines an explicit address.
The second line defines a range of addresses, a subnet, in standard TCP/IP format.
The third defines a range.

Reference “common” definitions.

You can specify IpSourceAddrRef, IpSourceAddrSetRef, IpSourceAddrGroupRef, to definitions defined elsewhere and refer to them. This allows you to share IP address definitions within rules.

  • IpSourceAddrRef is the name of an IpAddr statement.
  • IpSourceAddrSetRef is the name of a IpAddrSet which has either Prefix 10.1.0.0/24 or a Range 10.1.0.0-10.1.0.8
  • IpSourceAddrGroupRef is the name of an IpAddrGroup which has one or more IpAddr, IpAddrRef, IpAddrSet, or IpAddrSetRef statements.

Using Direction bidirectional drove me crazy.

To allow a connection from outside z/OS to an application running on z/OS (and getting a response back) you need definitions like:

IpSourceAddr LAPTOPIP IpDestAddr zOSIP … Direction inbound
IpSourceAddr zOSIP  IpDestAddr LAPTOPIP  … Direction outbound

To stay sane, do not use Directional bidirectional; you should explicitly specify the inbound and outbound connection.

The equivalent bidirectional definition looks like

IpSourceAddr zOSIP  IpDestAddr LAPTOP … Direction bidirectional

which generates the outbound statement then swaps the IP Address round, and generates an inbound. This makes my head spin… as the actual source is my laptop  and the target is z/OS – not the other way round. 

A ping request

A more detailed definition, to allow a ping request from my laptop to z/OS would include

IpSourceAddr LAPTOPIP IpDestAddr zOSIP … Direction inbound Protocol icmp Type 8
IpSourceAddr zOSIP  IpDestAddr LAPTOPIP  … Direction outbound Protocol icmp Type 0 …

A ping request is a packet with protocol type of icmp, and icmp-type of 8. The response to a ping is an icmp packet with icmp-type of 0. A definition using direction bidirectional would not work, as you can only specify one icmp type.

Of course you could have a definition without the type, so all icmp packets are accepted but that is an implementation decision.

Accessing a server on z/OS

I have an HTTP server on z/OS with port 443. The definitions are

IpSourceAddr LAPTOPIP IpDestAddr zOSIP … Direction inbound Protocol Tcp DestinationPortRange 443
IpSourceAddr zOSIP  IpDestAddr LAPTOPIP  … Direction outbound

The server has an IP address and port which I specify in my web browser. The definition for the return has no port, because it is variable (different invocations used ports 46938, and 46656 on the laptop).

If you know the range of ports that will be used you can specify DestinationPortRange nn mm and/or SourcePortRange nn mm.

Filter action DiscardAction didn’t work at first

When you have created a rule, you need to decide what action it should take.

You use the IpFilterAction to Permit or Deny the packet.

If the packet is to be discarded, then it can be silently dropped, with no further action ( so the requester does not get notified), or it can send back an ICMP packet to the requestor. If you use this, you will need to define a rule to allow these packets to get out of your TCPIP image, and so need a rule to allow icmp packets of type 3.

The documentation implied

IpFilterAction deny DiscardAction ICMP
IpFilterAction deny DiscardActionzzz ICMPzzz

The first line is the documented syntax, which is ignored. The second line did not produce any errors, event though it has invalid content.

The correct syntax is

IpFilterAction deny
DiscardAction ICMP

IpFilterAction deny
DiscardActionzzz ICMPzzz

With the values spread one per line. When I did this, it correctly complained that DiscardActionzzz ICMPzzz was invalid.

Why do I need to specify direction?

I struggled with why direction inbound/outbound is needed.

I have

IpFilterRule icmpin 
{
IpSourceAddr 10.1.0.2
IpDestAddr 10.1.1.2
IpGenericFilterActionRef permit
IpService
{
Protocol icmp
Direction inbound
Routing local
}
}

Where

  • IpSourceAddr 10.1.0.2 is my laptop
  • IpDestAddr 10.1.1.2 is z/OS

To send a packet from my laptop to z/OS the traffic is inbound.

IpFilterRule icmpout 
{
IpSourceAddr 10.1.1.2
IpDestAddr 10.1.0.2
IpGenericFilterActionRef permit
IpService
{
Protocol icmp
Direction outbound
Routing local
}
}

Where

  • IpSourceAddr 10.1.1.2 is my z/OS image
  • IpDestAddr 10.1.0.2 is my laptop.

To send a packet from my z/OS to my laptop, the direction is outbound.

I do not see what value having direction gives you!

Which rule is used?

For allow/deny

The short answer is all rules are scanned. If the criteria matches, and the action is deny the final result is denied.

For example with

  1. IpSourceAddr 10.1.0.3 IpDestAddr … IpGenericFilterActionRef allowit
  2. IpSourceAddr 10.1.0.0/24 IpDestAddr … IpGenericFilterActionRef denyit
  3. IpSourceAddr 10.1.0.2 IpDestAddr … IpGenericFilterActionRef allowit

For my laptop with address 10.1.0.2:

  • The first rule does not apply because the IpSourceAddress does not match
  • The second,generic rule matches and the action is deny, and future checks are not done.
  • The third rule matches but is ignored because the action has been set to deny.

For logging

The first matching rule is used. If you have a generic definition, followed by a specific definition, the definitions from the generic definition will be used.

CS IP filtering: allowing/denying packets flowing through z/OS

To see all my blog posts on IP filtering see here.

For the Communications Server on z/OS, you can define:

  • Default rules in the TCPIP profile, to allow traffic.
  • Named rules using Policy agent. These can allow or deny access.
  • Dynamic rules which can be automated, for example external monitors, using DMD to deny traffic. These are usually used in a problem situation to quickly deny traffic.

Writing of event messages is done using the TRMD task. The messages go to the syslogd daemon, to files in Unix.

Define default rules

The default default rule is to deny all access. You then specify rules to give access.

You can define default rules in the TCPIP profile – or replace them using an OBEYFILE

IPSEC LOGENable 
; Rule SourceIp DestIp Logging      Prot SrcPort   DestPort ...
  IPSECRULE 10.1.0.2 * LOG Protocol icmp Type 8 
  IPSECRULE * 10.1.0.2   LOG Protocol icmp 
ENDIPSEC 

This enables the default rules. It enables only

  • Ping traffic (icmp type 8) from 10.1.0.2 to any address
  • Any icmp from any address to 10.1.0.2. Note the response to ping is icmp type 0

If you use the OBEYFILE, the file contents replace any existing IPSEC default. So to add or remove an entry; edit the file, and use OBEYFILE to activate it.

Display the rules using

ipsec -f display -p TCPIP -c profile

The trace record looks like

EZD0814I Packet permitted: 11/18/2023 19:00:42.59 filter 
rule=SYSDEFAULTRULE.1 ext= 2 sipaddr= 10.1.0.2 dipaddr= 10.1.1.2 
proto= icmp(1) type= 8 code= 0 -= Interface= 10.1.1.2 (I) 
secclass= 255 dest= local len= 84 vpnaction= N/A tunnelID= 
N/A ifcname= ETH1 fragment= N 

Using the policy agent

The Policy agent uses a different syntax to using the IPSEC statments in the TCPIP profile. It can be used to allow and deny traffic (rather than just allow traffic). You can have common definitions which may make it easier to manage. It reads the policy from a file, and passes the policy to TCPIP.

Defensive rules

Defensive rules are created using the Unix command ipsec. The rules are used to deny (or simulate deny) traffic, and are typically used to restrict traffic in a problem situation. If you specify simulate, there is no impact to the traffic, but an event is written to syslogd.

If you use default rules or policy agent, you have to change a file, and redeploy it. With a defensive rule you define it, and it is immediately active.

You can delete an individual defensive rule.

Rather than have every event logged, which might overwhelm your system, it can be configured to provide summary records.

You can configure the defensive rule so that it expires after a time period.

CS IP filtering: planning the IP filtering rules

To see all my blog posts on IP filtering see here.

I have not configured the rules for a z/OS system, but from my experience of TCP/IP I can see some of the challenges, I hope this section gives you some help in planning your configuration

High level view

There are two approaches to locking down.

  1. Default: allow everything, deny access to specific sites
  2. Default: deny access. Specifically grant access to sites.

The second approach is better. If you “allow everything” by default and deny access to one IP address, the bad guys could use a different address not covered by your rules. If you deny access by default, and only allow the sites you want to use, it makes it harder for the bad guys.

What do I need to think about when planning rules?

From a planning perspective you need to consider several areas

  • The IP addresses of z/OS
  • The ports used by applications on z/OS
  • The IP addresses of client applications connecting to z/OS
  • The ports of used by the clients.
  • Whether to allow or deny access to the resource.

The configuration hierarchy

Information to help you plan your configuration.

A request allowed to pass into z/OS, will usually need a rule to allow the response to return to the requester, flowing out of z/OS. When planning my configuration, in my (paper) notebook, I had a page for requesters to z/OS, and another page for responses, and made sure they tied up.

  • Filter actions: deny|approve
    • Which server IP addresses? Can you create groups of IP addresses which can be reused by different filter rules, for example all LPARS, and all TCP Home addresses for each LPAR
    • Which client IP addresses? Can you create groups of IP addresses which can be reused by different filter rules? For example by country.
    • Within these,
      • Which ports , protocols (TCP/IP,icmp) and direction (inbound or outbound).

What actions should I configure?

There will be some events that will occur, business as usual traffic, which are not interesting, so you would define these so they are not logged.

Other events, such as from new client addresses, are interesting, and you should log these. Once you have put the new rules in place, you can then make them so they are not logged.

I think there are only four actions you should configure when starting to configure IP filtering.

  • IpGenericFilterActionRef permitlog
  • IpGenericFilterActionRef permitnolog
  • IpGenericFilterActionRef denylog
  • IpGenericFilterActionRef denynolog

Where the permitlog entry is defined as

IpGenericFilterAction permitlog 
{
IpFilterAction permit
IpFilterLogging yes
}

and the other filter actions are similar.

I tend to define a rule with permitlog, deploy it, then once it works, change it to permitnolog, and redeploy it, and check the event is not logged -if it is still logged; fix the rule!

You can have “deny” send back an icmp response saying “not allowed due to administrator”. See use of DiscardAction to send an icmp response back.

Background to z/OS IP Addresses

My laptop has a wireless connection, and an Ethernet connection to my server. Each of these interfaces has multiple IP address assigned to it (one IP V4 and multiple IPV6). In a similar way on z/OS each interface (think cable connected into z/OS) has an IP address. For example the TSO NETSTAT HOME command on my system gives me

IntfName:   ETH1                 
Address: 10.1.1.2
Flags: Primary
IntfName: ETH2
Address: 192.168.1.74
Flags:

To the outside world my z/OS has two interfaces ETH1 with IP address 10.1.1.2, and ETH2 with IP address 192.168.1.74.

You might have one interface which is for external facing connections, and another interface for your internal traffic.

For availability and capacity reasons you may have multiple interfaces per LPAR for internal traffic, and similarly for external traffic.

You may have multiple z/OS images and traffic can be routed to any of them. If you want to use global definitions (available to all systems) you need to include all home IP addresses across all interfaces across all z/OS images.

You also have IP V4, and IPV6.

z/OS addresses

You need to identify the IP addresses for those connections coming into z/OS, and the IP addresses of the z/OS systems. The number of z/OS systems should be limited, so you could define a group with the IP addresses of all your z/OS home addresses, across all LPARs.

z/OS ports

For applications running on z/OS, they will typically use one, or a few ports. For example a web server may have a port for TLS connections, and another port for unprotected connections.

If you wanted to gradually remove non TLS connections to your web server, you could create a rule, and say these IP addresses (from this office/area) can no longer use the unprotected port, and so gradually migrate every one to use the TLS connection.

You have to configure the ports inline – you cannot define them once, and refer to them, as you can with IP addresses

Client IP Addresses

Often the client will only have one address, think of wireless connected laptops. It may have a static address, the value of which is always the same, or it may get a dynamic IP address, which is “leased” the duration of the session. For example a DHCP address.

Dynamic addresses may be within a subnet, so for a particular DHCP server, the addresses may be within the range 10.4.5.0-10.4.5.255.

With my Wireless and Ethernet connections, most of the time my system uses the Ethernet connection. If I unplug this, then the wireless connection is used. With this, a client could have multiple addresses into z/OS, and you may need to cover all of them. You could configure it to accept data over my (ultra secure) direct wired Ethernet, but not over the wireless connection, or allow traffic only from a work location, and not from elsewhere.

Client IP port

A server usually has an allocated (well known) IP port. A client application typically uses bind() with port=0) and will then be assigned an unused port from the dynamic range. It can be given a reserved port.

With some products such as MQ Clients you can specify a port range which the application can use. This sort of application typically loops trying ports in the specified range until it finds a free port. You could use this to predefine a range of ports which you can then use IP Filtering to restrict the allowable range.

Baby steps for ICMP

Put your specific rules in front of your generic rules.

You could (I would not) configure rules

 IpFilterRule icmpall  
{
IpSourceAddr all
IpDestAddr all
IpGenericFilterActionRef permitnolog
IpService
{
Protocol icmp
Direction inbound
Routing local
}
}
IpFilterRule icmpspecific
{
IpSourceAddr 10.1.0.2
IpDestAddr all
IpGenericFilterActionRef permitlog
IpService
{
Protocol icmp
Direction inbound
Routing local
}
}

IpGenericFilterAction permitlog
{
IpFilterAction permit
IpFilterLogging yes
}
IpGenericFilterAction permitnolog
{
IpFilterAction permit
IpFilterLogging no
}

If IpFilterRule icmpall is before IpFilterRule icmpspecific the action for all is taken from icmpall; is permit and no log for all traffic – which maybe not what you want.

If these rules are swapped round, so the specific rule is first; traffic for 10.1.0.2 would get permit+log, and other traffic would get permit and no log.

You can then look in the logs to see the traffic, for example

EZD0814I Packet permitted: 12/04/2023 17:18:41.17 filter
rule= icmpinspecific ext= sipaddr= 10.1.0.2 dipaddr=10.1.1.2
proto= icmp(1) type= 8 code= 0 -= Interface=10.1.1.2 (I) secclass= 255 dest= local len= 84 vpnaction= N/A tunnelID= N/A ifcname= ETH1 fragment= N

From the information in the logs, you can refine your rules.

Testing the definitions

You can test your definitions (once you have deployed them) to see what rule is used for source and target IP addresses. See Testing the rules.

CS IP filtering:configuring Defence Manager Daemon (DMD)

To see all my blog posts on IP filtering see here.

With Communications Server(CS) on z/OS you can use filters to manage IP traffic in your TCPIP image. You can allow or deny a IP packet.

You can define

  • Default rules to allow traffic, in TCPIP Profile
  • To define a set of named rules using Policy agent. These can allow or deny access
  • Individual dynamic rules which can be automated, for example external monitors, using DMD

The ipsec command to define dynamic rules. It needs the DMD daemon to be running.

Update the syslogd daemon

You need a statement like

.DMD..* /var/log/DMD.%Y.%m.%d

In the /etc/syslog.conf file.

DMD started task JCL

This was copied from TCPIP.SEZAINST(EZADMD).

//DMD PROC 
//DMD EXEC PGM=DMD,REGION=0K,TIME=NOLIMIT, 
// PARM='ENVAR("_CEE_ENVFILE_S=DD:STDENV")/' 
//* DMD_FILE=/etc/security/dmd.conf 
//* DMD_CTRACE_MEMBER=CTIDMD00 
//* DMD_PIDFILE=/var/dm/dmd.pid 
//* DMD_CODEPAGE=IBM-1047 
//STDENV DD * 
DMD_FILE=//'USER.Z24C.TCPPARMS(DMD)' 
//SYSPRINT DD SYSOUT=* 
//SYSOUT DD SYSOUT=* 

My configuration file for testing is

DMConfig 
{ 
  SyslogLevel 7 
  DefensiveFilterDirectory /var/log/filters 
} 
DmStackConfig TCPIP 
{ 
  Mode  Simulate
} 

I do not know what authority it needs to run. It runs as userid START1 on my ADCD system.

You start it with S DMD .

You stop it using P DMD .

You can display information

f dmd,display

You can tell it to refresh its few lines of configuration.

F DMD,REFRESH
EZD1622I DEFENSE MANAGER DAEMON CONFIGURATION PROCESSING IS COMPLETE USING FILE //'USER.Z24C.TCPPARMS(DMD)'

CS IP filtering: common setup.

To see all my blog posts on IP filtering see here.

You can use the IP filtering component of z/OS Communications Servers to allow or deny packets flowing through a TCPIP stack.

You can use

  • CS default rules – configured in the TCPIP profile, or via an OBEYFILE
  • Policy agent
  • The ipsec command to dynamically add rules – this could be used by networking monitoring tools to defensively add new rules.

These all require common set up.

TCPIP profile

You need in the TCPIP profile

IPCONFIG  IPSECURITY...

Logging is done to the SYSLOGD daemon

You need to have the syslogd daemon running to write any event messages produced.
In /etc/syslog.conf I have

*.err            /var/log/errors 
*.CPAGENT.*.*       /var/log/CPAGENT.%Y.%m.%d 
*.TRMD1.*.info      /var/log/TRMD1I.%Y.%m.%d 
*.DMD.*.*           /var/log/DMD.%Y.%m.%d 
  • My policy agent job is called CPAGENT
  • My Defense Manager Daemon (DMD) is a started task with name DMD
  • I start TRMD, which logs events about the allow/deny rules. TRMD starts up a job TRMD1, and so the syslogd configuration needs to have TRMD1. The messages about allow/deny are written to syslogd as info and debug messages.

Traffic Regulation Management Daemon (TRMD)

This this writes events, about allow or deny packets through the TCPIP stack, to the syslogd daemon.

If this is not running, packets may still get allowed/denied, but will not be logged.

//TRMD      PROC  OPT='-P TCPIP -d 1' 
//* 
//*   IBM Communications Server for z/OS 
//*   SMP/E distribution name: EZATRMDP 
//* 
//*   5650-ZOS Copyright IBM Corp. 1996, 2013 
//*   Licensed Materials - Property of IBM 
//*   "Restricted Materials of IBM" 
//* 
//*   Status = CSV2R1 
//* 
//*   Function: Sample procedure for running the Traffic 
//*             Regulator Management Daemon (TRMD) 
//* 
//TRMD   EXEC PGM=EZATRMD,REGION=4096K,TIME=NOLIMIT, 
//      PARM=('ENVAR("_CEE_ENVFILE_S=DD:STDENV")/&OPT') 
//STDENV   DD * 
RESOLVER_CONFIG=//'ADCD.Z24C.TCPPARMS(TCPDATA)' 
export TZ=GMT0 

This daemon requires READ access to the profile BPX.SUPERUSER CL(FACILITY).

When you start TRMD you get

EZZ8495I TRMD STARTED                            
EZZ8500I TRMD INITIALIZATION COMPLETE            
IEF404I TRMD - ENDED - TIME=11.14.33             
$HASP395 TRMD     ENDED - RC=0000                

but it has started it creates a job with name TRMD1.

When running my TRMD1 the operator command D,A,TRMD1 gave

TRMD1    STEP1    START1   OWT  AO  ...  
                                    WKL=SERVERS  SCL=SRVOMVS  P=1                                        

You stop the TRMD daemon using

P TRMD1

You can display information from the log using the Unix command trmdstat

trmdstat … logname

Where logname is the trmd log from syslogd.

Policy Agent

If you want to define rules using Policy Agent, the Policy Agent job needs to be running. The Policy Agent just passes the rules to TCPIP, it does not do any processing of requests. To make a change to the rules, you change the policy agent files, and use the refresh policy agent command.

My policy agent procedure

//CPAGENT  PROC 
//  SET EN='ENVAR("_CEE_ENVFILE_S=DD:STDENV")' 
//PAGENT   EXEC PGM=PAGENT,REGION=0K,TIME=NOLIMIT, 
//       PARM='&EN/  -l /var/log/pagent.log -i -d 1 ' 
//STDENV   DD DISP=SHR,DSN=USER.Z24C.TCPPARMS(PAGENTEN) 
//SYSPRINT DD SYSOUT=H 
//SYSERR   DD SYSOUT=H 
//SYSOUT   DD SYSOUT=H 
//* 
//CEEDUMP  DD SYSOUT=*,DCB=(RECFM=FB,LRECL=132,BLKSIZE=132) 
// PEND 

Member USER.Z24C.TCPPARMS(PAGENTEN)

has

PAGENT_CONFIG_FILE=//'USER.Z24C.TCPPARMS(PAGENTCF)' 
LIBPATH=/usr/lib 

member PAGENTCF

has

tcpImage TCPIP   //'USER.Z24C.TCPPARMS(PAGENTT)' 

member PAGENTTT has

TTLSConfig //'USER.Z24C.TCPPARMS(PAGENTZ)' FLUSH PURGE 
IpSecConfig  //'USER.Z24C.TCPPARMS(PAGEIPSE)' FLUSH PURGE 

member PAGEIPSE

Started with the minimum configuration

#------------------------------------------------------- 

RACF profiles

IPSEC

See ipsec command SERVAUTH profile

RDEFINE SERVAUTH  EZB.IPSECCMD.*.*.DISPLAY
RDEFINE SERVAUTH  EZB.IPSECCMD.*.*.CONTROL
PERMIT  EZB.IPSECCMD.*.*.DISPLAY CLASS(SERVAUTH) ID(IBMUSER) -
    ACCESS(READ)  
PERMIT  EZB.IPSECCMD.*.*.CONTROL CLASS(SERVAUTH) ID(IBMUSER) -
    ACCESS(READ)
SETROPTS RACLIST(SERVAUTH) REFRESH                 

CS IP Filtering: start here

With Communications Server (CS) on z/OS, which I think of as the TCPIP started task, you can set up packet filtering. You define rules to allow or deny a packet into or out of TCP, based on criteria such as source IP address, destination IP port and address. The action can be to allow the packet into (or out of) TCP/IP, to quietly drop the packet, or to drop the packet but send an icmp response back to the originator. You can also log information about the packet. You could configure the rules so normal traffic is allowed access and not logged, but data from other addresses can be denied, and the event logged. You can review the traffic and set up rules to allow it, or to determine why someone is trying to access your system.

This is know as IPSECurity, and there is a product Vertali zTrust for Networks which interfaces to IPSEC and RACF to manage the environment using standard security tools.

There are three levels of rules

  • Default – these are configured when the TCPIP address space starts – ensuring you do not have a window when there are no rules defined. This might be deny access to all, except the system programmers.
  • From the Policy Agent – this is the normal source of rules.
  • Defensive rules – you can create additional rules on the fly for when there is a problem. These rules can be configured to expire after a time period, for example 30 minutes.

Set up

You have to configure several address spaces, for example:

  • TCPIP – to enable packet filtering, and to define the default(initial) rules.
  • Policy Agent to define the rules used in normal operation.
  • TRMD. This address space takes event information and writes it to the UNIX syslog daemon.
  • SYSLOGD. This is a central service which is sent event data, and the daemon writes the data to one or more files – depending on the configuration and the originating program. Without this events are not logged.
  • DMD – this processes the defensive rules and updates the TCPIP address space.

As usual there are started tasks to create, and define to WLM, security profiles to allow these started tasks to run, and profiles to allow users to administer IPSec packet filtering.

I have written some blog posts to help you navigate the journey. They are written to provide additional information to what is provided by IBM.

Blog posts