0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】HTTP通信でGETを直接書く(proxy経由)

Posted at

はじめに

前の投稿に続いて、今回はproxy を通すところを試してみました。これがやりたかった。

内容

まず、適当なサーバに対してGET を送り、レスポンス(短いのがいいな)が返ってくるの確認します。

$ curl http://google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

これをproxy経由にしてみます。

無料のproxy server

Google 先生に free proxy サーバと問い合わせてみると、いろいろなサイトを教えてくれます。
私は、以下から日本国内にあるものを見つけ、利用させていただくことにしました。

curl でproxy経由させたときの送受信

前回と同様にcURLを使って調べます。proxy server を指定するには、-x を使います。

$ curl -v google.com:80 -x http://116.80.45.7:80
*   Trying 116.80.45.7:80...
* TCP_NODELAY set
* Connected to 116.80.45.7 (116.80.45.7) port 80 (#0)
> GET http://google.com:80/ HTTP/1.1
> Host: google.com
> User-Agent: curl/7.68.0
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 08 Oct 2021 13:32:22 GMT
< Expires: Sun, 07 Nov 2021 13:32:22 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 0
< X-Frame-Options: SAMEORIGIN
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
* Connection #0 to host 116.80.45.7 left intact

リクエストの部分で、目的とするhost を書いています。このリクエストをproxy server に送っています。

python code で通信してみる

なので、同じことをしてみます。コードは前回のを少し変えてこんな感じです。

import socket
proxy_hostname, proxy_port = "116.80.45.7", 80
hostname, port = "google.com", 80
server_request = \
    f"GET http://{hostname}:{port}/ HTTP/1.1\r\n" \
    + f"Host: {hostname}:{port}\r\n" \
    + "User-Agent: MyPython\r\n" \
    + "Accept: */*\r\n\r\n"
print(f"request:\n{server_request}")
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5.0)
    s.connect_ex( (proxy_hostname, proxy_port) )
    #s.settimeout(None)
    ret = s.sendall(bytes(server_request, 'utf-8'))
except Exception as e:
    print(f"{e}")
    raise e

try:
    data = s.recv(8192*16)
    print( f"response({len(data)}):")
    print(data.decode('unicode-escape'))
except Exception as e:
    raise e

実行してみると、想定通り。

$ python3 python_proxy_get.py
request:
GET http://google.com:80/ HTTP/1.1
Host: google.com:80
User-Agent: MyPhthon
Accept: */*


response(528):
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 08 Oct 2021 13:28:44 GMT
Expires: Sun, 07 Nov 2021 13:28:44 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

無事に動いてます。やったー、今日は調子がいいぞ。

Proxy tunnel を通す(CONNECT メソドの登場)

ここで、curl のオプションに --proxytunnelを付けてみます。

$ curl -v google.com -x http://116.80.45.7:80 --proxytunnel
*   Trying 116.80.45.7:80...
* TCP_NODELAY set
* Connected to 116.80.45.7 (116.80.45.7) port 80 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to google.com:80
> CONNECT google.com:80 HTTP/1.1
> Host: google.com:80
> User-Agent: curl/7.68.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 405 Method Not Allowed
< Content-Type: text/html; charset=UTF-8
< Referrer-Policy: no-referrer
< Content-Length: 1592
< Date: Fri, 08 Oct 2021 13:17:05 GMT
< Connection: close
<
* Received HTTP code 405 from proxy after CONNECT
* CONNECT phase completed!
* Closing connection 0
curl: (56) Received HTTP code 405 from proxy after CONNECT

先程のpython script でリクエストヘッダを書き換えます。

server_request = \
    f"CONNECT {hostname}:{port}/ HTTP/1.1\r\n" \
    + f"Host: {hostname}:{port}\r\n" \
    + "User-Agent: MyPython\r\n" \
    + "Accept: */*\r\n\r\n"

とりあえず同じものを送れるようにはなり、同じ結果が返ってきました。

まとめ

HTTP Proxy を理解するために、curl で送受信されるデータを見て、同じ内容をpython で送ってみた。
とりあえず、これでproxy を通すベタな実装はできる気がした。

本当は、おじさんは便利なモジュールを使いたいのだ。そうなのだが誰も教えてくれないので、自分で実装しているのです。
(2021/10/08)

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?