You can create configuration blocks that are only applicable to a specific subset of hosts.
The Match all block matches all hosts and is equivalent to Host *.
The Match Canonical All block applies to all hosts that have undergone canonicalization.
Use Match canonical all instead of Match !canonical to be sure that the configuration option is only applied to hosts that have undergone canonicalization and not too those hosts where explicit hostname has been specified.
Match all is default. If you want to apply options on all hosts, with or without canonicalization, then choose that option.
If you want to apply it only for hosts that undergo canonicalization, then create additional Match blocks below that specify what is allowed by your options
The ssh client connects to a host and determines the first matching configuration file. If there are multiple matching files, the options in the first matching Host or Match block take precedence.
In order for the CanonicalizeHostname option to work properly, you must enable the double-pass parsing mode. During each pass of parsing, filters and Match blocks are evaluated for every hostname in your configuration file. The filters are evaluated first, followed by the Match blocks.
You can add options to the Match blocks based on their intended scope. If the option applies to all hosts, place it under Match all. If it applies only to hosts that have undergone canonicalization, create a new Match block with those options and apply them accordingly.
Sources:
Hostname canonicalisation in OpenSSH
Some notes on OpenSSH's optional hostname canonicalization
How to perform hostname canonicalization
Host Restricts the following declarations (up to the next Host
or Match keyword) to be only for those hosts that match one
of the patterns given after the keyword. If more than one
pattern is provided, they should be separated by
whitespace. A single ‘*’ as a pattern can be used to
provide global defaults for all hosts. The host is usually
the hostname argument given on the command line (see the
CanonicalizeHostname keyword for exceptions).
A pattern entry may be negated by prefixing it with an
exclamation mark (‘!’). If a negated entry is matched,
then the Host entry is ignored, regardless of whether any
other patterns on the line match. Negated matches are
therefore useful to provide exceptions for wildcard
matches.
See PATTERNS for more information on patterns.
ssh_config(5) — Linux manual page
Examples:
# Match on hostname
Match Host example.com
# Match ip
Match Address 192.168.178.*
# Match on user
Match User alice
# Match based on group
Match Group admin
# Multiple criteria
Match Host example.com User alice
# Match multiple criteria, use this key for some hosts
Match canonical,Host host.domain.cocom,192.168.178.100
IdentityFile ~/.ssh/my_key
# Match multiple criteria, disable port forwarding for some hosts
Match canonical,Host *.domain.com,*.internal,192.168.178.*
ForwardAgent no
ForwardX11 no
CanonicalizeHostname yes
CanonicalDomains example.org example.com
CanonicalizeMaxDots 1
CanonicalizeFallbackLocal yes
CanonicalizePermittedCNAMEs *.redis.example.org:redis.example.com
How is Match All different to Host *?
Host * matches all hosts, thus the configuration directives that
follow will be applied to all hosts. The hostname can appear anywhere
in the pattern you use (either as part of the pattern itself, or at
the end after an asterisk).
A "Match All" keyword is used to group all the configuration directives that apply to a particular host. When you use "Match All", you don't need to specify a pattern, as it will match all hosts by default.
Examples:
Host *
<config directives>
Host *
StrictHostKeyChecking no
Match All
<config directives>
Match All
Compression yes
What does Match canonical all mean? Why would the canonical hosts be directed to parse that option again when it has already been set for them in a different way? If it was !canonical it would make more sense to me, although seemingly redundant, as in this case the single directive under it has already been set.
Match canonical all is a configuration option that applies to all canonical hosts, which are hosts whose name can be fully qualified by the DNS domain name search algorithm. The "canonical" keyword in SSH means that the hostname must be fully qualified, as opposed to an alias or shortened version of the hostname.Regarding the second part of your question, if a configuration option is set for a host using a specific directive, and that host matches a "Match" block with the same option
"Match canonical all" applies to all canonical hosts, and if a host matches both a specific directive and a "Match" block with the same option, the "Match" block takes precedence. The "!" in "!canonical" means "not canonical". So, "Match !canonical" applies to non-canonical hosts that cannot be fully qualified by DNS domain name search algorithm
The canonical host matching option can be used on a per-host basis. A
host matches if is listed in the DNS zone file, has an address
configured using iproute2 and routes packets between interfaces of the
same network device. If a host does not meet these criteria, then it
doesn't match canonically
When the CanonicalizeHostname option is enabled in SSH, the hostname of the remote host is parsed twice: first, when the connection is established, and second, when the SSH client applies any Match blocks that have a CanonicalizeHostname directive. If you have a Match block with a CanonicalizeHostname directive that applies to a canonical host, the host's name will be parsed twice, and the configuration option in the Match block will take precedence over any specific directive that was set earlier.