izackwu / blog

My personal blog.
https://www.zackwu.com
MIT License
10 stars 4 forks source link

为什么用 Go 访问某网站始终会 503 Service Unavailable ? #50

Open izackwu opened 3 years ago

izackwu commented 3 years ago

https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/#%E5%B0%BE%E5%A3%B0

记一次耗费了我三天精力,但是相当有趣的 Debug 经历

Gitalk_/posts/2021-03-14-why-i-always-get-503-with-golang/

Xuanwo commented 3 years ago

看标题的时候就在想会是什么原因,没想到居然是 Cipher Suites 导致的,神奇

holmesian commented 3 years ago

给大佬点赞,之前我有一次爬数据的时候也遇到了类似的问题,因为时间紧,后来直接改用了Python,原来坑在这里

Zheaoli commented 3 years ago

很有趣的问题

实际上看起来这个网站的活做的很细,某种程度上让人更难排查

laike9m commented 3 years ago

这反爬🤣 看来是被 go 搞怕了 所以如果使用第三方的 go HTTP 库会怎样呢,不知道是不是还是同一套 cipher suites

Allianzcortex commented 3 years ago

大胆假设,小心求证

izackwu commented 3 years ago

@laike9m

那得看第三方的 HTTP 库有没有用 Go 的 TLS 库的默认参数了,我感觉应该不太可能自己实现一个 TLS 库

Wusuluren commented 3 years ago

用go爬微博的个人主页也会被防,换成python就可以

yihong0618 commented 3 years ago

cloudflare 利用了部分 Cipher Suites 的特性做 anti-bot code

izackwu commented 3 years ago

@yihong0618 学到了

yihong0618 commented 3 years ago

我又来了,哈哈, 之前发现可以强制指定 tls 版本绕过一些例如 anti-bot, 想试试这网站行不行。 但再尝试发现,这网站已经可以用 go 直接访问了不会 503...太奇怪了(可能是服务器升级了。)

qiankunxienb commented 3 years ago

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

Zheaoli commented 3 years ago

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

    myClient := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MaxVersion: tls.VersionTLS12,
            },
        },
    }
    request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

qiankunxienb commented 3 years ago

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

  myClient := &http.Client{
      Transport: &http.Transport{
          TLSClientConfig: &tls.Config{
              MaxVersion: tls.VersionTLS12,
          },
      },
  }
  request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

Zheaoli commented 3 years ago

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

    myClient := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MaxVersion: tls.VersionTLS12,
            },
        },
    }
    request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

    myClient := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MaxVersion: tls.VersionTLS12,
            },
        },
    }
    request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

HTTP2 加上 ForceAttemptHTTP2: true 就行

qiankunxienb commented 3 years ago

@Zheaoli

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

  myClient := &http.Client{
      Transport: &http.Transport{
          TLSClientConfig: &tls.Config{
              MaxVersion: tls.VersionTLS12,
          },
      },
  }
  request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

  myClient := &http.Client{
      Transport: &http.Transport{
          TLSClientConfig: &tls.Config{
              MaxVersion: tls.VersionTLS12,
          },
      },
  }
  request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

HTTP2 加上 ForceAttemptHTTP2: true 就行

加上ForceAttemptHTTP2: true 以后,上面使用的tls.VersionTLS12就会失效。于是又不能请求这个网址了。

Zheaoli commented 3 years ago

@Zheaoli

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

    myClient := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MaxVersion: tls.VersionTLS12,
            },
        },
    }
    request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

@Zheaoli 这样做,这个网站确实可以了。因为这个网站同时支持http/2和http/1.1两种协议。如果有网站它只支持http/2,那这样做就不能访问网站了。

博主可以试一试这个网站:https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series 即使改了Cipher Suites,用net/http也无法请求成功。但Python的httpx就能轻松成功。

和 Chiper Suite 有关系,Go 很奇葩的在 TLS 1.2 的 Chiper Suite 里加入了三个 TLS 1.3 专属的 Suite TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_256_GCM_SHA384,特征太过于明显了,以及这个站对 UserAgent 对 Go Client 做了拦截

    myClient := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MaxVersion: tls.VersionTLS12,
            },
        },
    }
    request, err := http.NewRequest("GET", "https://www.gizmochina.com/2021/06/23/redmi-gm-lu-weibing-stylishly-teases-the-redmi-k50-series/", nil)

你这样处理下就行

HTTP2 加上 ForceAttemptHTTP2: true 就行

加上ForceAttemptHTTP2: true 以后,上面使用的tls.VersionTLS12就会失效。于是又不能请求这个网址了。

I see, 我大概知道原因了。。这个站实际上 HTTP2 要求必须在 TLS1.3 ,但是 Go 的 TLS1.3 的特征又太过于明显。。。我看看怎么样绕过或者是给 Go 提个 PR。。。

izackwu commented 2 years ago

https://go.dev/blog/tls-cipher-suites

才发现 Go 官方最近(两个月前)写了篇文章讲新版本 Go 的 cipher suites 设计逻辑,有兴趣的话大家可以读一下

yihong0618 commented 2 years ago

Cool

Molin-L commented 2 years ago

我遇到的情况和你一模一样,不过原因是python自动走系统代理,go不会

0fv commented 2 years ago

🤣遇到过类似的问题,爬的亚马逊网站,不过亚马逊更狠,判断了第一位密码套件,第一位是grease位,go都没实现

saber3188 commented 1 year ago

惊呆了,我也碰到了这个问题,完全没往这方面想