Using TCPIP Port with SAF

I had configured my TCPIP to have

PORT 
...
3023 TCP * SAF VERIFY ; COLIN PAICE

This says

  • 3023 is the port number
  • TCP for when the request is TCP ( and not UDP)
  • * Any job
  • SAF check with the SAF interface
  • VERIFY. This is part of the RACF resource name.

I used X3270 to provide TLS sessions into z/OS. When TN3270 started (or was refreshed), I got

EZZ6035I TN3270 DEBUG CONFIG EXCEPTION
 LINE: N/A MOD: EZBTMCVU
 RCODE: 8020-00 Initialization of the Telnet Port failed.
 PARM1: 0000102B PARM2: 3023 PARM3: 00000000
EZZ6038I TN3270 COMMAND OBEYFILE COMPLETE
EZZ6035I TN3270 DEBUG TASK EXCEPTION 766
 TASK: MAIN MOD: EZBTZMST
 RCODE: 1018-01 The Port task has ended in error.
 PARM1: 0000102B PARM2: 00000BCF PARM3: 00000000

I could not find parm1 (0000102B) defined anywhere.

I defined the SERVAUTH profile EZB.PORTACCESS.*.*.* with fail WARN, and I got a message

ICH408I USER(TCPIP ) GROUP(OMVSGRP ) NAME(TCPIP
EZB.PORTACCESS.S0W1.TCPIP.VERIFY CL(SERVAUTH)
 WARNING: INSUFFICIENT AUTHORITY – TEMPORARY ACCESS ALLOWED
 FROM EZB.PORTACCESS...* (G)
 ACCESS INTENT(READ ) ACCESS ALLOWED(NONE )

Where

  • SOW1 is my z/OS system
  • TCPIP is my TCPIP image name
  • VERIFY – is the value in the TCPIP configuration file

With the RACF definition I did not get the error message.

I then defined a proper profile for it.

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.

Setting up FTP Server on z/OS

I had problems using the FTP server on z/OS once I had configured IP Filtering (any IP addresses and ports which are not in the configuration are dropped).

Once an FTP client has established contact using port 21, the transfer switches to a different port. You can control which port range is used.

Setting up the FTP server.

If you start the FTP Daemon (S FTPD) it starts up another procedure (FTPD1) and the initial job ends.

You need to configure the SYSLOGD daemon to capture any output from the FTP task.

In /etc/syslog.conf I set up

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

so any output from jobs with a name FTPD* will go into the specified file.

In my file I had

EZYFT46E Error in dd:SYSFTPD=TCPIP.SEZAINST(FTPSDATA) file: line 1283 near column 1.
EZY2642E Unknown keyword: PASSIVEDATAPORTS(8000,8100)

Configuring ports

To limit which ports FTP uses you need to specify PASSIVEDATAPORTS

PASSIVEDATAPORTS (8000,8100)

with a blank between the keyword and the (.

You also need to tell TCPIP that the port range is reserved for TCPIP’s use for example

PORTRANGE
... 50000 100 TCP AUTHPORT

Where AUTHPORT Indicates that all ports in the port range are not available for use by any user except FTP, and only when FTP is configured to use PASSIVEDATAPORTS. AUTHPORT is valid only with the TCP protocol.

When you try to transfer a file you get a message

ftp> get ‘…’ … local: …: ‘…’
229 Entering Extended Passive Mode (|||8061|)

where 8061 is the port which was used.

IPSEC definitons for IP Filtering

For my very restrictive access from my laptop to z/OS (and no other devices) I used

IpFilterRule FTPnI21 
{
IpSourceAddrGroupRef zGroup
IpSourceAddr 10.1.0.2
IpDestAddr 10.1.1.2
IpGenericFilterActionRef permitlog
IpService
{
Protocol Tcp
DestinationPortRange 21
Direction inbound
Routing local
}
IpService
{
Protocol Tcp
DestinationPortRange 8000-8100
Direction inbound
Routing local
}
}

and

IpFilterRule FTPO21 
{
IpSourceAddr 10.1.1.2
IpDestAddr 10.1.0.2
IpGenericFilterActionRef permitlog
IpService
{
Protocol Tcp
SourcePortRange 21
Direction outbound
Routing local
}
IpService
{
Protocol Tcp
SourcePortRange 8000-8100
Direction outbound
Routing local
}
}

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.