diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp
index a2bad90d8507d2..bce567f95f8d98 100644
--- a/src/app/server/Dnssd.cpp
+++ b/src/app/server/Dnssd.cpp
@@ -207,7 +207,7 @@ CHIP_ERROR DnssdServer::AdvertiseOperational()
                                        .SetPort(GetSecuredPort())
                                        .SetInterfaceId(GetInterfaceId())
                                        .SetLocalMRPConfig(GetLocalMRPConfig().std_optional())
-                                       .EnableIpV4(true);
+                                       .EnableIpV4(SecuredIPv4PortMatchesIPv6Port());
 
 #if CHIP_CONFIG_ENABLE_ICD_SERVER
         AddICDKeyToAdvertisement(advertiseParameters);
@@ -234,7 +234,7 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi
     auto advertiseParameters = chip::Dnssd::CommissionAdvertisingParameters()
                                    .SetPort(commissionableNode ? GetSecuredPort() : GetUnsecuredPort())
                                    .SetInterfaceId(GetInterfaceId())
-                                   .EnableIpV4(true);
+                                   .EnableIpV4(!commissionableNode || SecuredIPv4PortMatchesIPv6Port());
     advertiseParameters.SetCommissionAdvertiseMode(commissionableNode ? chip::Dnssd::CommssionAdvertiseMode::kCommissionableNode
                                                                       : chip::Dnssd::CommssionAdvertiseMode::kCommissioner);
 
diff --git a/src/app/server/Dnssd.h b/src/app/server/Dnssd.h
index 1fef479ca3eba4..1b82fb909653a7 100644
--- a/src/app/server/Dnssd.h
+++ b/src/app/server/Dnssd.h
@@ -24,6 +24,7 @@
 #include <app/icd/server/ICDStateObserver.h>
 #include <app/server/CommissioningModeProvider.h>
 #include <credentials/FabricTable.h>
+#include <inet/InetConfig.h>
 #include <lib/core/CHIPError.h>
 #include <lib/core/Optional.h>
 #include <lib/dnssd/Advertiser.h>
@@ -46,11 +47,16 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
         return instance;
     }
 
-    /// Sets the secure Matter port
-    void SetSecuredPort(uint16_t port) { mSecuredPort = port; }
+    /// Sets the secure Matter IPv6 port
+    void SetSecuredIPv6Port(uint16_t port) { mSecuredIPv6Port = port; }
+
+#if INET_CONFIG_ENABLE_IPV4
+    /// Sets the secure Matter IPv4 port.
+    void SetSecuredIPv4Port(uint16_t port) { mSecuredIPv4Port = port; }
+#endif // INET_CONFIG_ENABLE_IPV4
 
     /// Gets the secure Matter port
-    uint16_t GetSecuredPort() const { return mSecuredPort; }
+    uint16_t GetSecuredPort() const { return mSecuredIPv6Port; }
 
     /// Sets the unsecure Matter port
     void SetUnsecuredPort(uint16_t port) { mUnsecuredPort = port; }
@@ -176,6 +182,18 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
     //
     bool HaveOperationalCredentials();
 
+    // Check whether the secured IPv4 port matches the secured IPv6 port.  If it
+    // does not, we should not advertise our IPv4 bits, because we can only
+    // advertise one port number.
+    bool SecuredIPv4PortMatchesIPv6Port() const
+    {
+#if INET_CONFIG_ENABLE_IPV4
+        return mSecuredIPv4Port == mSecuredIPv6Port;
+#else
+        return false;
+#endif // INET_CONFIG_ENABLE_IPV4
+    }
+
     FabricTable * mFabricTable                             = nullptr;
     CommissioningModeProvider * mCommissioningModeProvider = nullptr;
 
@@ -187,7 +205,10 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
     bool mTCPServerEnabled = true;
 #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
 
-    uint16_t mSecuredPort          = CHIP_PORT;
+    uint16_t mSecuredIPv6Port = CHIP_PORT;
+#if INET_CONFIG_ENABLE_IPV4
+    uint16_t mSecuredIPv4Port = CHIP_PORT;
+#endif // INET_CONFIG_ENABLE_IPV4
     uint16_t mUnsecuredPort        = CHIP_UDC_PORT;
     Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
 
diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp
index 5aa7577606cc13..e9586c6a7c2775 100644
--- a/src/app/server/Server.cpp
+++ b/src/app/server/Server.cpp
@@ -216,12 +216,17 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
     }
 
     // Init transport before operations with secure session mgr.
+    //
+    // The logic below expects that the IPv6 transport is at index 0. Keep that logic in sync with
+    // this code.
     err = mTransports.Init(UdpListenParameters(DeviceLayer::UDPEndPointManager())
                                .SetAddressType(IPAddressType::kIPv6)
                                .SetListenPort(mOperationalServicePort)
                                .SetNativeParams(initParams.endpointNativeParams)
 #if INET_CONFIG_ENABLE_IPV4
                                ,
+                           // The logic below expects that the IPv4 transport, if enabled, is at
+                           // index 1. Keep that logic in sync with this code.
                            UdpListenParameters(DeviceLayer::UDPEndPointManager())
                                .SetAddressType(IPAddressType::kIPv4)
                                .SetListenPort(mOperationalServicePort)
@@ -318,13 +323,10 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
     SuccessOrExit(err);
 #endif
 
-    //
-    // We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
-    // and IPv6 endpoint to pick from. Given that the listen port passed in may be set to 0 (which then has the kernel select
-    // a valid port at bind time), that will result in two possible ports being provided back from the resultant endpoint
-    // initializations. Since IPv6 is POR for Matter, let's go ahead and pick that port.
-    //
-    app::DnssdServer::Instance().SetSecuredPort(mTransports.GetTransport().GetImplAtIndex<0>().GetBoundPort());
+    app::DnssdServer::Instance().SetSecuredIPv6Port(mTransports.GetTransport().GetImplAtIndex<0>().GetBoundPort());
+#if INET_CONFIG_ENABLE_IPV4
+    app::DnssdServer::Instance().SetSecuredIPv4Port(mTransports.GetTransport().GetImplAtIndex<1>().GetBoundPort());
+#endif // INET_CONFIG_ENABLE_IPV4
 
     app::DnssdServer::Instance().SetUnsecuredPort(mUserDirectedCommissioningPort);
     app::DnssdServer::Instance().SetInterfaceId(mInterfaceId);
diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp
index cbc29de5f86338..b537f01fe3ecd1 100644
--- a/src/controller/CHIPDeviceControllerFactory.cpp
+++ b/src/controller/CHIPDeviceControllerFactory.cpp
@@ -169,13 +169,18 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
     stateParams.transportMgr = chip::Platform::New<DeviceTransportMgr>();
 
     //
-    // The logic below expects IPv6 to be at index 0 of this tuple. Please do not alter that.
+    // The logic below expects IPv6 to be at index 0 of this tuple. Keep that logic in sync with
+    // this code.
     //
     ReturnErrorOnFailure(stateParams.transportMgr->Init(Transport::UdpListenParameters(stateParams.udpEndPointManager)
                                                             .SetAddressType(Inet::IPAddressType::kIPv6)
                                                             .SetListenPort(params.listenPort)
 #if INET_CONFIG_ENABLE_IPV4
                                                             ,
+                                                        //
+                                                        // The logic below expects IPv4 to be at index 1 of this tuple,
+                                                        // if it's enabled. Keep that logic in sync with this code.
+                                                        //
                                                         Transport::UdpListenParameters(stateParams.udpEndPointManager)
                                                             .SetAddressType(Inet::IPAddressType::kIPv4)
                                                             .SetListenPort(params.listenPort)
@@ -272,13 +277,15 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
             stateParams.exchangeMgr, stateParams.sessionMgr, stateParams.fabricTable, sessionResumptionStorage,
             stateParams.certificateValidityPolicy, stateParams.groupDataProvider));
 
-        //
-        // We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
-        // and IPv6 endpoint to pick from. Given that the listen port passed in may be set to 0 (which then has the kernel select
-        // a valid port at bind time), that will result in two possible ports being provided back from the resultant endpoint
-        // initializations. Since IPv6 is POR for Matter, let's go ahead and pick that port.
-        //
-        app::DnssdServer::Instance().SetSecuredPort(stateParams.transportMgr->GetTransport().GetImplAtIndex<0>().GetBoundPort());
+        // Our IPv6 transport is at index 0.
+        app::DnssdServer::Instance().SetSecuredIPv6Port(
+            stateParams.transportMgr->GetTransport().GetImplAtIndex<0>().GetBoundPort());
+
+#if INET_CONFIG_ENABLE_IPV4
+        // If enabled, our IPv4 transport is at index 1.
+        app::DnssdServer::Instance().SetSecuredIPv4Port(
+            stateParams.transportMgr->GetTransport().GetImplAtIndex<1>().GetBoundPort());
+#endif // INET_CONFIG_ENABLE_IPV4
 
         //
         // TODO: This is a hack to workaround the fact that we have a bi-polar stack that has controller and server modalities that
diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp
index 0ecf30640d90a5..f43ded783f8bc5 100644
--- a/src/lib/dnssd/Discovery_ImplPlatform.cpp
+++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp
@@ -22,6 +22,7 @@
 
 #include <app/icd/server/ICDServerConfig.h>
 #include <crypto/RandUtils.h>
+#include <inet/InetConfig.h>
 #include <lib/core/CHIPConfig.h>
 #include <lib/core/CHIPSafeCasts.h>
 #include <lib/dnssd/IPAddressSorter.h>
@@ -527,7 +528,7 @@ CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextE
                                                  const OperationalAdvertisingParameters & params)
 {
     return PublishService(serviceType, textEntries, textEntrySize, subTypes, subTypeSize, params.GetPort(), params.GetInterfaceId(),
-                          params.GetMac(), DnssdServiceProtocol::kDnssdProtocolTcp, params.GetPeerId());
+                          params.GetMac(), DnssdServiceProtocol::kDnssdProtocolTcp, params.GetPeerId(), params.IsIPv4Enabled());
 }
 
 CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize,
@@ -535,13 +536,13 @@ CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextE
                                                  const CommissionAdvertisingParameters & params)
 {
     return PublishService(serviceType, textEntries, textEntrySize, subTypes, subTypeSize, params.GetPort(), params.GetInterfaceId(),
-                          params.GetMac(), DnssdServiceProtocol::kDnssdProtocolUdp, PeerId());
+                          params.GetMac(), DnssdServiceProtocol::kDnssdProtocolUdp, PeerId(), params.IsIPv4Enabled());
 }
 
 CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize,
                                                  const char ** subTypes, size_t subTypeSize, uint16_t port,
                                                  Inet::InterfaceId interfaceId, const chip::ByteSpan & mac,
-                                                 DnssdServiceProtocol protocol, PeerId peerId)
+                                                 DnssdServiceProtocol protocol, PeerId peerId, bool ipv4Enabled)
 {
     DnssdService service;
     ReturnErrorOnFailure(MakeHostName(service.mHostName, sizeof(service.mHostName), mac));
@@ -549,11 +550,17 @@ CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextE
                              ? MakeInstanceName(service.mName, sizeof(service.mName), peerId)
                              : GetCommissionableInstanceName(service.mName, sizeof(service.mName)));
     Platform::CopyString(service.mType, serviceType);
-#if INET_CONFIG_ENABLE_IPV4
-    service.mAddressType = Inet::IPAddressType::kAny;
-#else
-    service.mAddressType = Inet::IPAddressType::kIPv6;
-#endif
+#if !INET_CONFIG_ENABLE_IPV4
+    ipv4Enabled = false;
+#endif // INET_CONFIG_ENABLE_IPV4
+    if (ipv4Enabled)
+    {
+        service.mAddressType = Inet::IPAddressType::kAny;
+    }
+    else
+    {
+        service.mAddressType = Inet::IPAddressType::kIPv6;
+    }
     service.mInterface     = interfaceId;
     service.mProtocol      = protocol;
     service.mPort          = port;
diff --git a/src/lib/dnssd/Discovery_ImplPlatform.h b/src/lib/dnssd/Discovery_ImplPlatform.h
index d51d5e758c0268..f57171a7bb9556 100644
--- a/src/lib/dnssd/Discovery_ImplPlatform.h
+++ b/src/lib/dnssd/Discovery_ImplPlatform.h
@@ -85,9 +85,10 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
                               size_t subTypeSize, const OperationalAdvertisingParameters & params);
     CHIP_ERROR PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize, const char ** subTypes,
                               size_t subTypeSize, const CommissionAdvertisingParameters & params);
+    // ipv4Enabled will be ignored if we don't actually support IPv4.
     CHIP_ERROR PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize, const char ** subTypes,
                               size_t subTypeSize, uint16_t port, Inet::InterfaceId interfaceId, const chip::ByteSpan & mac,
-                              DnssdServiceProtocol procotol, PeerId peerId);
+                              DnssdServiceProtocol procotol, PeerId peerId, bool ipv4Enabled);
 
     static void HandleNodeIdResolve(void * context, DnssdService * result, const Span<Inet::IPAddress> & addresses,
                                     CHIP_ERROR error);