绕过SNI审查直连Pixiv


简述

2020/1/31的情况:www.pixiv.net有污染和阻断故无法通过常规手段访问,其APP端的app-api.pixiv.net只有污染,图床i.pximg.net可正常访问。因此,我们可以通过Cloudflare的公众DNS获取真实ip,从而进行访问app-api.pixiv.net,从其中的api中进行登录与查询,最终实现从图库中获取图片。(从图库中获取图片需要refer为Pixiv网域)

实现

先写代码查询DNS:

# encoding = utf-8
import requests
if __name__ == '__main__':
    hostname = "app-api.pixiv.net"
    url = "https://1.0.0.1/dns-query" # 查询DNS
    params = {
        'ct': 'application/dns-json',
        'name': hostname,
        'type': 'A',
        'do': 'false',
        'cd': 'false',
    }
    response = requests.get(url, params=params)
    print(response.json())

Out:

{
    'Status': 0,
    'TC': False,
    'RD': True,
    'RA': True,
    'AD': False,
    'CD': False,
    'Question': [{
        'name': 'app-api.pixiv.net.',
        'type': 1
    }],
    'Answer': [{
            'name': 'app-api.pixiv.net.',
            'type': 1,
            'TTL': 150,
            'data': '210.140.131.220'
        },
        {
            'name': 'app-api.pixiv.net.',
            'type': 1,
            'TTL': 150,
            'data': '210.140.131.223'
        },
        {
            'name': 'app-api.pixiv.net.',
            'type': 1,
            'TTL': 150,
            'data': '210.140.131.225'
        }
    ]
}

显然,获取其中一个IP即可。接下来尝试登录:

import hashlib
from datetime import datetime

client_id = 'MOBrBDS8blbauoSck0ZfDbtuzpyT' # 假装APP应用登录
client_secret = 'lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj'
hash_secret = '28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c'
local_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S+00:00')
headers = {
    'host': 'oauth.secure.pixiv.net',
    'User-Agent': 'PixivAndroidApp/5.0.64 (Android 6.0)',
    'X-Client-Time': local_time,
    'X-Client-Hash': hashlib.md5((local_time + hash_secret).encode('utf-8')).hexdigest(),
    'Accept-Language': 'en-us'
}
data = {
    'get_secure_url': 1,
    'client_id': client_id,
    'client_secret': client_secret,
    'grant_type': 'password', #认证类型,有token与password两种
    'username': pixiv_id, # 用户名
    'password': password # 密码
}
response = requests.post('https://210.140.131.220' + '/auth/token', headers=headers, data=data, stream=False,
                            verify=False)
print(response.text)

Out:

{
    "response": {
        "access_token": "omWoN1QUQ4OF9ENF4LTHObdR9K5eB1COACnOavlG5J1",
        "expires_in": 3600,
        "token_type": "bearer",
        "scope": "",
        "refresh_token": "3ysYSnD71aFttkt1XgBr-XxwjiMOGtdBmaAZbYFT2e1",
        "user": {
            "profile_image_urls": {
                "px_16x16": "https:\/\/i.pximg.net\/user-profile\/img\/2018\/02\/11\/13\/24\/32\/13810489_848de9cbfdb78a44b1319634ccee5d31_16.jpg",
                "px_50x50": "https:\/\/i.pximg.net\/user-profile\/img\/2018\/02\/11\/13\/24\/32\/13810489_848de9cbfdb78a44b1319634ccee5d31_50.jpg",
                "px_170x170": "https:\/\/i.pximg.net\/user-profile\/img\/2018\/02\/11\/13\/24\/32\/13810489_848de9cbfdb78a44b1319634ccee5d31_170.jpg"
            },
            "id": "11111111",
            "name": "Ryan",
            "account": "user_ynvp1111",
            "mail_address": "123456789@qq.com",
            "is_premium": false,
            "x_restrict": 1,
            "is_mail_authorized": true
        },
        "device_token": "4fae17434ceedc22a7da75ca27a1a7b1"
    }
}

顺便收到了一条Pixiv事务局发来的email,表明从中国登录。由上绕过SNI,成功登录并获取了bearer token,下次可以直接填入登录。

完善代码

# encoding = utf-8
import hashlib
import requests
from datetime import datetime


if __name__ == '__main__':
    hostname = "app-api.pixiv.net"
    timeout = 3
    # url = "https://cloudflare-dns.com/dns-query"
    url = "https://1.0.0.1/dns-query"
    params = {
        'ct': 'application/dns-json',
        'name': hostname,
        'type': 'A',
        'do': 'false',
        'cd': 'false',
    }
    try:
        response = requests.get(url, params=params, timeout=timeout)
    except Exception:
        # 部分地区可能无法访问1.0.0.1,此时尝试域名解析
        url = "https://cloudflare-dns.com/dns-query"
        response = requests.get(url, params=params, timeout=timeout)

    # response = requests.get("http://"+"210.140.131.220", params=params,headers=header())
    # print(response.text)
    client_id = 'MOBrBDS8blbauoSck0ZfDbtuzpyT'
    client_secret = 'lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj'
    hash_secret = '28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c'
    local_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S+00:00')
    headers = {
        'host': 'oauth.secure.pixiv.net',
        'User-Agent': 'PixivAndroidApp/5.0.64 (Android 6.0)',
        'X-Client-Time': local_time,
        'X-Client-Hash': hashlib.md5((local_time + hash_secret).encode('utf-8')).hexdigest(),
        'Accept-Language': 'en-us'
    }
    data = {
        'get_secure_url': 1,
        'client_id': client_id,
        'client_secret': client_secret,
        'grant_type': 'password',
        'username': pixiv_id,
        'password': password
    }
    response = requests.post("https://" + response.json()['Answer'][0]['data'] + '/auth/token', headers=headers,
                             data=data, stream=False,
                             verify=False)
    print(response.text)

登陆后可通过app-api.pixiv.net的接口进行各类操作,IP已经获取,因此只需在IP上进行相对路径即可。

附录

常见的API及JSON格式:


评论
  目录