diff --git a/lib/bb/fetch2/gomod.py b/lib/bb/fetch2/gomod.py
index 5cdf8f998..7bb91e2a0 100644
--- a/lib/bb/fetch2/gomod.py
+++ b/lib/bb/fetch2/gomod.py
@@ -48,7 +48,10 @@ Optional SRC_URI parameters:
 Related variables:
 
 - GO_MOD_PROXY
-    The module proxy used by the fetcher.
+    The module proxy used by the fetcher. Supports a pipe-separated list of
+    proxies tried in order, matching Go's GOPROXY syntax (e.g.
+    "goproxy.cn|proxy.golang.org|direct"). The special value "direct" is
+    skipped (direct VCS fetching is handled by the gomodgit fetcher).
 
 - GO_MOD_CACHE_DIR
     The directory where the module cache is located.
@@ -97,7 +100,7 @@ class GoMod(Wget):
         cache/download/<module>/@v/<version>.mod: The go.mod file.
         """
 
-        proxy = d.getVar('GO_MOD_PROXY') or 'proxy.golang.org'
+        proxy_setting = d.getVar('GO_MOD_PROXY') or 'proxy.golang.org'
         moddir = d.getVar('GO_MOD_CACHE_DIR') or 'pkg/mod'
 
         if 'version' not in ud.parm:
@@ -109,14 +112,24 @@ class GoMod(Wget):
         ud.parm['module'] = module
         version = ud.parm['version']
 
-        # Set URL and filename for wget download
+        # Parse pipe-separated proxy list (Go GOPROXY syntax); drop "direct"
+        # entries since direct VCS fetching is the job of the gomodgit fetcher.
+        proxies = [p for p in proxy_setting.split('|') if p.strip() and p.strip() != 'direct']
+        if not proxies:
+            proxies = ['proxy.golang.org']
+        ud.parm['proxies'] = proxies
+
+        # Set URL and filename for wget download.  Use the first proxy for
+        # urldata_init so that localpath / checksum keys are stable regardless
+        # of which proxy ultimately serves the file.
         if ud.parm.get('mod', '0') == '1':
             ext = '.mod'
         else:
             ext = '.zip'
         path = escape(f"{module}/@v/{version}{ext}")
+        ud.parm['mod_path'] = path
         ud.url = bb.fetch2.encodeurl(
-            ('https', proxy, '/' + path, None, None, None))
+            ('https', proxies[0], '/' + path, None, None, None))
         ud.parm['downloadfilename'] =  f"{module.replace('/', '.')}@{version}{ext}"
 
         # Set name for checksum verification
@@ -127,6 +140,24 @@ class GoMod(Wget):
 
         super().urldata_init(ud, d)
 
+    def download(self, ud, d):
+        """Try each proxy in GO_MOD_PROXY in order, falling back on failure."""
+        proxies = ud.parm.get('proxies', ['proxy.golang.org'])
+        path = ud.parm['mod_path']
+        last_exc = None
+        for proxy in proxies:
+            ud.url = bb.fetch2.encodeurl(
+                ('https', proxy, '/' + path, None, None, None))
+            try:
+                super().download(ud, d)
+                return
+            except FetchError as e:
+                bb.warn(f"GoMod: proxy {proxy} failed for {ud.parm['module']}: {e}, trying next proxy")
+                last_exc = e
+        raise FetchError(
+            f"All proxies failed for {ud.parm['module']}@{ud.parm['version']}: {last_exc}",
+            ud.url)
+
     def unpack(self, ud, rootdir, d):
         """Unpack the module in the module cache."""
 
diff --git a/lib/bb/tests/fetch.py b/lib/bb/tests/fetch.py
index d021ad786..76b2e203c 100644
--- a/lib/bb/tests/fetch.py
+++ b/lib/bb/tests/fetch.py
@@ -3815,6 +3815,28 @@ class GoModTest(FetcherTest):
         self.assertEqual(bb.utils.sha256_file(os.path.join(downloaddir, 'go.opencensus.io/@v/v0.24.0.mod')),
                          '0dc9ccc660ad21cebaffd548f2cc6efa27891c68b4fbc1f8a3893b00f1acec96')
 
+    def test_gomod_multi_proxy_uses_first_proxy(self):
+        """First non-direct proxy in GO_MOD_PROXY is used to build ud.url."""
+        urls = ['gomod://golang.org/x/net;version=v0.9.0;'
+                'sha256sum=d9b70a10f88ededacb4e0e974de5d5a98e3db9c1e0e01c4dbfe5a5279b65a0c']
+        self.d.setVar('GO_MOD_PROXY', 'goproxy.cn|proxy.golang.org|direct')
+
+        fetcher = bb.fetch2.Fetch(urls, self.d)
+        ud = fetcher.ud[urls[0]]
+        self.assertIn('goproxy.cn', ud.url)
+        self.assertEqual(ud.parm['proxies'], ['goproxy.cn', 'proxy.golang.org'])
+
+    def test_gomod_direct_only_falls_back_to_default(self):
+        """A GO_MOD_PROXY of 'direct' (only) falls back to proxy.golang.org."""
+        urls = ['gomod://golang.org/x/net;version=v0.9.0;'
+                'sha256sum=d9b70a10f88ededacb4e0e974de5d5a98e3db9c1e0e01c4dbfe5a5279b65a0c']
+        self.d.setVar('GO_MOD_PROXY', 'direct')
+
+        fetcher = bb.fetch2.Fetch(urls, self.d)
+        ud = fetcher.ud[urls[0]]
+        self.assertEqual(ud.parm['proxies'], ['proxy.golang.org'])
+        self.assertIn('proxy.golang.org', ud.url)
+
 class GoModGitTest(FetcherTest):
 
     @skipIfNoNetwork()
