CS IP filtering: defining dynamic rules for IP traffic

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

With Communications Server(CS) on z/OS you can 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

Dynamic rules

You can use the Unix command ipsec -F to add,delete or modify individual rules. These rules might be generated by an external monitoring scheme, which can say to devices

“we seem to have a problem – use this rule to stop traffic from this destination while the CS people investigate and update the rules in the policy agent”

an example is

ipsec -F add srcip 10.1.0.2 destip all prot icmp dir inbound mode block log yes loglimit 1 lifetime 30 -N COLIN1 -p TCPIP

This defines a rule called COLIN1 on TCPIP address space TCPIP. Note you can specify a global rule for all TCPIP address spaces, by specifying -G instead of -p TCPIP

  • Source IP address 10.1.0.2
  • Destination IP address all
  • Only ICMP prototols
  • Direction inbound
  • Mode block. You can use Simulate to allow the packet – but to write an event to the log. This is useful when building rules.
  • Log – write it to the syslogd log
  • Loglimit – this logs at an average rate of 1 event per 5 minutes – so you can avoid flooding the logs.
  • Lifetime – this rule expires after 30 minutes.

Display all dynamic rules

ipsec -F display -p TCPIP

and delete it

ipsec -F delete -N COLIN1 -p TCPIP

When you add a rule, you get information In the log such as

EZD1723I Defensive filter added: 11/21/2023 08:58:10.86 filter rule= COLIN1 ext= 1 
sipaddr= 10.1.0.2 / 32 dipaddr= 0.0.0.0 / 0 proto= icmp(1) type= all code= all fragmentsonly= no dir= inbound routing= local mode= block log= yes lifetime= 30 
userid= IBMUSER global= no loglimit= 1

Log limited output

If you specify loglimit:

The value specifies the limit of the average rate of filter-match messages generated in a 5-minute interval for a defensive filter.

You get a trace message like

EZD0838I Defensive filter packet would have been denied messages limited: 
11/21/2023 13:04:22.92 filter_rule= COLIN2 filter_ext= 1 
filter_sipaddr= 10.1.0.2 / 32  filter_dipaddr= 0.0.0.0 / 0 
filter_proto= icmp(1) type= 8 code= all  filter_fragmentsonly= no filter_dir= inbound filter_routing= local suppressed_count= 274 

This shows there were 274 suppressed messages

EZD0838I:This message is issued when limiting of filter match messages was requested for a defensive filter and at least one “packet would have been denied” message (EZD1722I) for the defensive filter was suppressed during the preceding five minutes.

Suppressed counts: The number of “packet would have been denied” messages (EZD1722I) for the defensive filter that were suppressed during the preceding five minutes.

CS IP filtering: understanding logged messages

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

If you are using Communications Server IP filtering to allow/deny IP traffic to destinations, you need the TMDR daemon running. TMDR writes messages to the syslogd which can write them to a file

The trace output is like

EZD0815I Packet denied by policy: 11/17/2023 13:09:17.00 filter rule= Colin 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

The request

  • came from 10.1.0.2 ( the Source IP ADDRress)
  • going to 10.1.1.2 the (Destination IP ADDRess
  • The protocol was icmp. Within the IP protocol an icmp packet has type 1.
  • Type is Echo request (used to called ping), and icmp packet with type 8. See here.
  • The name of the z/OS interface definition ETH1. See NETSTAT DEVLINKS
  • The IP address of the interface 10.1.1.2
  • The packet was inbound(I)
  • There was a keyword with no value -= … this is useful when parsing the traffic, because it shows a null object.

Using the Unix System Services command

ipsec -p TCPIP -f display > a

This gave

...
FilterName:                   Colin 
FilterNameExtension:          1 
...
Direction:                    Outbound 
...
FilterName:                   Colin 
FilterNameExtension:          2 
...
Direction:                    Inbound 

From filter rule= Colin ext= 2 we can see this was inbound.

With an input file

IpFilterPolicy 
{ 
  PreDecap off 
  FilterLogging on 
  IpFilterLogImplicit yes 
  AllowOnDemand yes 
  IpFilterRule Colin 
  { 
    IpSourceAddr 10.1.1.2 
    IpDestAddr   All 
    IpService 
    { 
      Protocol all 
      Direction bidirectional 
      Routing local 
    } 
    IpService 
    { 
#  PING  ICMP type 8 
      Protocol icmp Type 8 
      Direction bidirectional 
      Routing local 
    } 
    IpGenericFilterActionRef permit 
    IpService 
    { 
# 
      Protocol icmp Type 9 
      Direction bidirectional 
      Routing local 
    } 
} 

With Direction bidirectional it creates two rules, one in bound, and one outbound.

When PING was performed – this was rule 4 – from the bold text.

CS IP filtering: understanding the display output of the ipsec -f display command

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

The list below are the fields I found interesting ( mainly because they were not “n/a”)

FilterName: COLIN1

The name comes from

  • COLIN1 comes from a defensive rule like ipsec -F add … -N COLIN1, or from the name of an Policy rule IpFilterRule.
  • SYSDEFAULTDENYRULE comes from the default default rule
  • SYSDEFAULTRULE.1 comes from the default rule .1 means the first rule in the file


FilterNameExtension: 1

There can be more than one rule from a definition. For example a Direction bidirectional will create an inbound and an outbound rule. Within an IpFilterRule there can be multiple IpService definitions, each potentially with Direction bidirectional. The extension will increase for each rule.

Type: Defensive

It can be Generic if created by Policy Agent.

DefensiveType: Stack

For Type: Defensive it can be Global or Stack. For other type it is n/a.

State: Active

This always seems active (in the current list)

Action: Defensive Block

This can be Defensive Block, Deny, or Permit.

Scope: Local

Direction: Inbound

Or outbound.


SecurityClass: 0

You can classify interfaces with a security class of 1 to 255. 0 Means not specified.

Logging: All

Indicates the logging that is to be performed when the filter is invoked. Possible values are:

  • All: A log entry is generated if data traffic is permitted or denied.
  • Permit: A log entry is generated only when data traffic is permitted.
  • Deny: A log entry is generated only when data traffic is denied.
  • None: No log entries are generated from this filter.

LogLimit: 1

Used to summarise the number of times defensive rules are logged.

Protocol: ICMP(1)

For example UDP, TCP, igmp.

SourceAddress…: 10.1.0.2

There are several fields which define the source address:

SourceAddress, such as 10.1.1.2

  • Source Address: such as 10.1.1.2
  • SourceAddressPrefix, 24 as in IpSourceAddr 10.1.1.2/24
  • SourceAddressRange, 11.2.1.2 as in IpSourceAddr 10.1.1.2-11.2.1.2
  • SourceAddressGranularity, used in dynamic tunnels and dynamic VPNs.

A value of 0.0.0.0 is all.

SourcePort: and SourcePortrange

For example SourcePortRange 600 604 gives SourcePort 600 and SourcePortRange 604.

DestAddress: 0.0.0.0

See SourceAddress above.

DestPort…:

See SourcePort above

CreateTime: 2023/11/22 17:57:26

The time it was first activated (the time the TCPIP stack created its entry).

UpdateTime: 2023/11/22 17:57:26

The time it was last changed within the TCPIP stack.

DiscardAction: Silent

Indicates the discard action for packets that are discarded as a result of this filter rule. Possible values are:

  • Silent: Packets are discarded silently.
  • ICMP: When a packet is discarded, an ICMP or ICMPv6 error is sent to the origin of the discarded packet to indicate that the packet was administratively prohibited.


FilterMatches: 0

For a defensive filter the number of times this rule has been hit.

LifetimeExpires: 2023/11/22 18:27:26

For a defensive filter the time this rule will expire.


CS IP filtering: configuring TMDR – Traffic Management Daemon Regulation

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

If you are using Communications Server IP filtering to allow/deny IP traffic to destinations, you need the TRMD daemon running. With IP filtering you can log when access is allowed/denied.

The TRMD is needed to write the log events.

TRMD started task JCL

//TRMD      PROC  OPT='-P TCPIP -d 1' 
//* 
//*   IBM Communications Server for z/OS 
//*   SMP/E distribution name: EZATRMDP 
//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 
/* 
//SYSPRINT DD SYSOUT=*,DCB=(RECFM=F,LRECL=80,BLKSIZE=80) 
//SYSIN    DD DUMMY 
//SYSERR   DD SYSOUT=* 
//SYSOUT   DD SYSOUT=*,DCB=(RECFM=F,LRECL=80,BLKSIZE=80) 
//CEEDUMP  DD SYSOUT=*,DCB=(RECFM=FB,LRECL=132,BLKSIZE=132) 

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

When you start it, it starts up a job with name TMDR1, and the “started task” TMDR ends.

You stop it using P TMDR1.

Logging

The syslogd daemon needs to be running.

In my /etc/syslog.conf file I have

*.TRMD1.*.info      /var/log/TRMD1I.%Y.%m.%d 
*.TRMD1.*.debug     /var/log/TRMD1D.%Y.%m.%d 

Both of these write the access/denied messages – you would typically just have one of these.

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: 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.