← すべての記事

Proxy Port: ユーザー名によるターゲティングとセッション管理

FourAのproxyポートはネットワーク、国、スティッキーセッションをユーザー名から読み取り、入力ミス時には有効なキー名を含む400エラーを返します。その構文仕様を解説します。

新機能

たった1文字の欠落が問題を引き起こします。proxyのユーザー名に-contry-deと入力した場合、その誤字は一見して正常なオプションのように見えてしまいます。

FourAのproxyポートは、認識可能なすべてのキーをリストした400エラーでこれに応答します。これは9月15日にベータ版を終了した製品の細かな仕様の1つです。APIコールを記述することなく、proxyに対応する任意のクライアント (ブラウザ、ダウンロードツール、既存のスクレイパーなど) で使用できるエグジットのproxy URLを提供します。Dashboardでproxyユーザーを作成してその文字列を貼り付けるだけで、トンネルとトラフィックはAPIリクエストと同様にプランの消費量としてカウントされます。

以下に構文の全体と、各ルールが設けられた理由を説明します。

仕組み

このポートはproxy.foura.ai:34004でリッスンし、ポート443および80のターゲットに対してBasic認証を伴うHTTP CONNECTを処理します。認証情報はAPIキーとは意図的に分離されたproxyユーザーです。proxyのハンドシェイクは平文で送信されるため、proxyユーザーを分けることでAPI連携に影響を与えることなくパスワードを更新できます。

認証情報の後には、任意の順序で-key-valueのペアが続きます。

# Shared network, a German address, one sticky session for this job
curl -x "http://USERNAME-country-de-session-job42:PASSWORD@proxy.foura.ai:34004" \
  https://example.com

# Premium network, an Android address in Germany, held 30 minutes
curl -x "http://USERNAME-network-premium-country-de-os-android-session-s1-lifetime-30:PASSWORD@proxy.foura.ai:34004" \
  https://example.com

SharedはFourA自前の出口です。デフォルト設定であり、プランに含まれています。Premiumは住宅用アドレスであり、プランのプレミアムトラフィックおよび追加購入分から消費されます。Sharedネットワーク上では、-fallback-premiumを指定することで、Shared側で処理できない場合にコネクションをPremium出口へ移行できます。明示的に指定しない限り無効であり、Premiumの利用可能残量がある間のみ動作します。これをデフォルトで有効化することは、お客様に代わってその利用枠を消費することを意味してしまうためです。

国は複数指定可能なため、-country-de-country-frは2か国を対象とするスコープになります。地域、都市、AS番号によるネットワーク、デバイス(windows、android、ios、mac)、およびlifetime(3から1440分)はPremium専用です。Sharedネットワークで都市を指定した場合は、ベストエフォートでの処理ではなく400エラーが返されます。ほぼ満たすことができない都市フィルターはフィルターが存在しない状態よりも有害であるため、Sharedでは国単位でのみ選択可能とし、それ以上の細かな指定は受け付けません。

-session-<name>(1から32文字の英数字またはアンダースコア)はコネクションを固定化します。その名前を持つすべてのコネクションで同一のアドレスが共有されます。Sharedでは10分間のスライディングウィンドウでアドレスが維持されるため、使用し続ける限り持続します。Premiumでは設定したlifetime、またはネットワークのデフォルト値の間維持されます。セッションを省略した場合は、コネクションごとに新しいアドレスから送信されます。

また、保存されたデフォルト設定もあります。Dashboardのプロキシユーザーに保存されたターゲティングは、そのユーザーが行うすべてのコネクションに適用されるため、文字列を最低限の認証情報のみに縮小できます。コネクション固有のユーザー名の指定が常に優先され、anyによって保存された値をリセットできます。たとえば-city-anyは、ミュンヘンを記憶しているキーに対してドイツ全体を要求します。CONNECTにヘッダーを付与できるクライアント(curlでは--proxy-headerを使用)は、X-Foura-CountryやX-Foura-Sessionなどのヘッダーとして同一のオプションを送信でき、ヘッダーはユーザー名での指定よりも優先されます。

影響

これらの多くは、開発者が不要な疑問を抱かずに済む仕組みとして機能します。

なぜ拒絶されたのか? 認証情報の検証後に発生するすべての拒絶には、1行の理由を含むX-Foura-Errorヘッダーが付与されます。400エラーではオプション名と受け入れ可能な値が示されます。429エラーでは、プランの制限値のうちどれに達したか(同時オープン中のトンネル数、1分あたりのトンネルオープン数、または請求期間の標準トラフィック)が示されます。

利用枠は誰のものか? アカウントのものです。トンネル数とオープン数はプロキシユーザー単位ではなくアカウント単位でカウントされるため、認証情報を追加しても利用枠は増えません。バイト数はプランの帯域幅にカウントされ、Premiumのバイト数はその合計枠内のPremium利用枠にカウントされます(合算して加算されることはありません)。クレジット課金プランの場合、ポートには固有のギガバイトが含まれており、Billingページから補充できます。トンネルが開かない限り何もカウントされません。

認証情報の所有者は誰か? 組織(organization)を所有者にできるようになりました。これにより、1人のメンバーが離脱しても会社のダウンローダーが停止することはありません。メンバーは認証情報を使用してパスワードを閲覧でき、管理者とオーナーはローテーション、無効化、または再ターゲティングを行えます。移動できるのはオーナーのみです。

何ができるようになったか Overview、Metrics、またはActivityのProductスイッチをProxyに切り替えると、API requestと同じ結果クラスのトンネル、現在のオープン数、セットアップ時間、トラフィックが確認できます。これらはproxyユーザー、ターゲット、出口国、クライアントIPごとに分割して表示されます。すでにアドレスが割り当てられているsessionは、通常1秒未満で接続されます。

ただし、ポートは単なるパイプであり、トレードオフが存在します。クライアントはトンネル経由でサイトと直接通信するため、アンブロッカーやvalidate rules、ブラウザベースのチャレンジ解決はその経路に介在しません。また、バイト数も計測されます。APIでは失敗したrequestは課金されませんが、開いたトンネルを通じて返される拒否ページは通常のバイトとしてカウントされます。大量のバイト転送にはポートを使用し、ブロックされるページにはAPIを使用してください。

パワーユーザー向け

プレミアム枠を使い切ると、そのネットワークへの3つのルートに対して、意図的に3種類の結果が返されます。-network-premiumを指定した接続は、その旨を示す403で拒否されます。別の場所から暗黙的に処理されると、呼び出し元が要求を続け、請求書に記載されないプレミアム枠を探すことになるためです。フォールバックは実行されず、proxyユーザーに保存されたプレミアムデフォルトは共有ネットワークへ降格されるため、トンネル自体は引き続き開きます。どちらもその接続での追加消費は選択していません。

中途半端に処理するのではなく、完全に拒否される組み合わせが3つあります。共有ネットワークでの詳細なターゲティング、-fallback-premiumと-network-premiumの併用、そしてフォールバック有効時の詳細なターゲティングです。ポートはCONNECTのみをサポートするため、トンネリングせずにプレーンなhttp:// requestを転送するクライアントには405が返されます(curlでは--proxytunnelでトンネリングします)。また、1回のページ読み込みで数十の接続が開かれるため、ポート経由でブラウザを操作する場合は必ずsession名を指定してください。

複数のワーカーがそれぞれ独自のアドレスを持つ構成の場合は、各ワーカーに個別のsession名を割り当てます。

import requests

TEMPLATE = "http://USERNAME-country-de-session-{name}:PASSWORD@proxy.foura.ai:34004"

def worker_session(name):
    proxy = TEMPLATE.format(name=name)
    s = requests.Session()
    s.proxies = {"http": proxy, "https": proxy}
    return s

workers = [worker_session(f"w{i}") for i in range(4)]
print(workers[0].get("https://example.com").status_code)

Dashboardでも同様の操作を大規模に実行できます。Stickyを設定し、数を指定すると、Connection stringタブにアドレスごとに1行ずつ、URLまたはproxyマネージャー向けのhost:port:user:pass形式で一覧表示されます。拒否の理由を調査する場合は、curlの呼び出しに-svを追加し、2>&1 | grep -i x-foura-errorにパイプしてください。すべてのオプションはproxy port referenceに記載されており、Dashboard側の設定はProxy Usersにあります。

What's Next

proxy userをベースに構築した最初のクライアントは自社製ツールです。FourA Chrome extensionを使用すると、ブラウザの通信をそのいずれかを経由してルーティングできます。ネットワークと国を選択してスイッチを切り替えると、サイト側に認識されるアドレスがステータス行に表示されます。これはベータ版であり、Chrome Web Storeには公開されておらず、デベロッパーモードのDashboardのToolsからインストールします。さらに先の実装として、公開ロードマップにorganization billingが予定されています。組織のproxy userによる利用分は、現在その組織を所有しているアカウントに課金されるため、この機能が重要になります。

proxy URLは最も古くから存在する連携インターフェースであり、既存のあらゆるツールがすでに対応しています。真に最適化すべき対象は、トンネルそのものではありませんでした。その手前にある文字列がどのような意味を持ち得るか、そしてそれを誤って解釈した際に何が起きるかという点です。