tor代理搭建

使用tor解决爬虫ip问题

Posted by HugoNgai on February 10, 2020

前言

最近准备在服务器上跑爬虫,首先要解决的问题就是IP的问题。常见的解决IP的方式是购买代理池服务,但是对于个人用户来说不友好,费用相当高。因此,tor代理就在这时派上了用场。

正文

准备

  • 安装tor

服务器上装的是Centos7系统,在这里就只介绍Centos7的安装方式。其他系统的安装方式大同小异,具体可以google一下。

  • 首先update一下yum源,添加tor的repo

    sudo yum install epel-release
    sudo yum install tor
    
  • 安装完成以后,启动tor服务

    sudo systemctl start tor
    sudo systemctl enable tor  # 设置开机自启
    sudo systemctl status tor  # 查看tor运行状态,显示为active表示启动成功
    
  • 配置tor服务

    这一步网上的教程里面一般讲的不详细,中间遇到的坑会比较多。

    • 先测试一下是否可以连接tor代理服务

      sudo yum install nc
      echo -e 'AUTHENTICATE' | nc 127.0.0.1 9051
      

      不出意外,输出应该是Connection refused。

      这里使用netcat来测试tor代理端口的连接情况,具体关于netcat的介绍,可以看我的另外一篇blog。

      我们需要先配置一下tor服务的ControlPort

      echo "ControlPort 9051" >> /etc/tor/torrc
      # 这里的端口可以自定义,设置完成后记得防火墙打开该端口的监听
      

      Tor的配置文件目录为etc/tor/torrc,可以使用vim在配置文件结尾添加或者只用用命令写入文件结尾。重启tor服务:

      sudo systemctl restart tor
      

      再用netcat测试一遍

      echo -e 'AUTHENTICATE' | nc 127.0.0.1 9051
      #  515 Authentication failed: Wrong length on authentication cookie.
      

      网上很多教程在设置完ControlPort这一步以后就停止了,其实这里还有一个坑,就是我们要设置一个HashedControlPortPassword,即端口密码。这个密码是tor通过hash生成的密码。生成方式很简单,使用tor来生成即可:

      echo HashedControlPassword $(tor --hash-password "my password" | tail -n 1) >> /etc/tor/torrc
      # 使用tor --hash-password + 你设置的密码生成hash密码,然后追加写入到配置文件最后一行
      

      这里建议命令使用不熟悉的还是用vim的方式手动写入,免得少打一个>符号,把文件覆盖掉了。

      查看一下写入情况:

      tail -n -2 /etc/tor/torrc
      # ControlPort 9051
      # HashedControlPassword 16: .......
      # 写入成功,重启tor
      systemctl restart tor
      

      再次使用netcat测试一下

      echo -e 'AUTHENTICATE "my password"' | nc 127.0.0.1 9051
      # 250 OK
      

      至此配置已经大功告成。

  • 测试tor服务的使用

    • 测试一下服务器的公网IP和使用tor代理访问的IP,看看tor服务是否生效

      curl http://icanhazip.com/
      # 你的公网IP
      torify curl http://icanhazip.com/
      # tor代理访问的IP
      
    • 切换IP测试;这里有两种方式,第一种是通过命令来进行切换:

      echo -e 'AUTHENTICATE "my password"\r\nsignal NEWNYM\r\nQUIT' | nc 127.0.0.1 9051
      # 第一段 echo -e 'AUTHENTICATE "my password" 为测试服务连通性
      # signal NEWNYM 命令表示切换IP
      # QUIT 命令表示断开连接
      

      再运行一次上面的命令看下IP有没有成功切换

      torify curl http://icanhazip.com/
      # 如无意外,这次输出的IP应该是成功切换
      
    • 使用python脚本来进行IP切换

      pip3 install stem
      python3 # 运行python shell,如未安装python请先安装
      >>> from stem import Signal
      >>> from stem.control import Controller
      >>> 
      >>> with Controller.from_port(port=9051) as controller:
      ...     controller.authenticate()
      ...     controller.signal(Signal.NEWNYM)
      ... 
      >>> 
      

      通过stem库,可以使用python与tor服务进行交互,有关stem库使用,可以查看一下文档

      至此,tor代理配置全部完成。

搭配privoxy食用

privoxy是何方神圣,详情请Google一下。

  • 安装privoxy

    yum install privoxy
    
  • 配置privoxy服务并启动

    echo "forward-socks5t / 127.0.0.1:9050 ." >> /etc/privoxy/config
    systemctl enable privoxy
    systemctl start privoxy
    systemctl status privoxy
    
  • 尝试通过privoxy使用tor

    torify curl http://icanhazip.com/
    curl -x 127.0.0.1:8118 http://icanhazip.com/
    # 不出意外,两个命令的输出应该一致,说明privoxy配置服务成功
    # privoxy默认使用8118端口监听服务,使用前请先检查8118端口是否被其他服务占用
    
  • 用python测试一下搭配privoxy后的食用效果

    import requests
    from stem import Signal
    from stem.control import Controller
      
    def switch_proxy():
      	with Controller.from_port(port=9051) as controller:
          	controller.authenticate(password='my password')
            controller.signal(Signal.NEWNYM)
      
    for i in range(10):
      	switch_proxy()
        response = requests.get('http://icanhazip.com/', proxies={'http': '127.0.0.1:8118'})
        response.text.strip()
    
  • bonus: 使用toripchanger切换代理

    pip3 install toripchanger
    
    from toripchanger import TorIpChanger
    import os
      
    """
    	# 这里如果不想把密码写在代码里,可以在环境变量中配置 
    	export tor_password="my password"
    	tor_ip_changer = TorIpChanger(tor_password=os.getenv('tor_password'), tor_port=9051, local_http_proxy='127.0.0.1:8118')
    """
    tor_ip_changer = TorIpChanger(tor_password='my password', tor_port=9051, local_http_proxy='127.0.0.1:8118')
      
    tor_ip_changer.get_current_ip()		# 查看当前IP
      
    tor_ip_changer.get_new_ip()		# 切换IP
    
  • 指定特定的地区IP

    在/etc/tor/torrc文件中添加一下语句

    ExcludeNodes {cn},{hk},{mo},{kp},{ir},{sy},{pk},{cu},{vn} # 表示排除这些国家/地区的节点
    StrictNodes 1 # 表示强制执行
    

备注:关于privoxy中的echo "forward-socks5t / 127.0.0.1:9050 ." >> /etc/privoxy/config,9051端口是用于tor代理的ControlPort,9050端口为tor代理的SocketPort的默认值。