CS IP Filtering: Trying to use FTP

With my FTP, the initial connection worked on port 21, then it switched to use a different port for the file transfer. These were not set up on my system. 

On my FTP client, I received

229 Entering Extended Passive Mode (|||1028|)

which means it was trying to use port 1028. This was not configured, and so the transfer failed.

You have to configure FTP to use a range of ports, and then configure the Policy Agent with these ports.

In the FTPD JCL I have

//FTPD   PROC MODULE='FTPD',PARMS='' 
//FTPD EXEC PGM=&MODULE,REGION=4096K,TIME=NOLIMIT,
// PARM='POSIX(ON) ALL31(ON)/&PARMS'
//CEEDUMP DD SYSOUT=*
//SYSFTPD DD DISP=SHR,DSN=TCPIP.FTP.DATA
//* SYSTCPD explicitly identifieS which file iS to be
//* uSed to obtain the parameterS defined by TCPIP.DATA.
//* The SYSTCPD DD Statement Should be placed in the JCL of
//* the Server. The file can be any Sequential data Set,
//*SYSTCPD DD DISP=SHR,DSN=TCPIP.SEZAINST(TCPDATA)
//SYSTCPD DD DISP=SHR,DSN=ADCD.&SYSVER..TCPPARMS(TCPDATA)

Within the SYSFTPD dataset you need to configure the PASSIVEDATAPORTS statement.

See setting up FTP Daemon on z/OS.

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

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