web-dev-qa-db-ja.com

透過プロキシとしてのMITMf?

MITMfを使用して透過プロキシとしてスニッフィングすることは可能ですか?このプロキシに接続する場合、サーバーIPではなく実際のIPを表示したいと思います。可能であれば、どうすればよいですか?このファイル「ClientRequest.py」を見つけましたが、Pythonがわかりません。たぶん誰かが私がヘッダーを編集しないようにプロキシを設定するのを手伝ってくれるでしょうか?

class ClientRequest(Request):

    ''' This class represents incoming client requests and is essentially where
    the magic begins.  Here we remove the client headers we dont like, and then
    respond with either favicon spoofing, session denial, or proxy through HTTP
    or SSL to the server.
    '''

    def __init__(self, channel, queued, reactor=reactor):
        Request.__init__(self, channel, queued)
        self.reactor       = reactor
        self.urlMonitor    = URLMonitor.getInstance()
        self.cookieCleaner = CookieCleaner.getInstance()
        self.dnsCache      = DnsCache.getInstance()
        #self.uniqueId      = random.randint(0, 10000)

    def cleanHeaders(self):
        headers = self.getAllHeaders().copy()

        if 'accept-encoding' in headers:
             del headers['accept-encoding']
             log.debug("[ClientRequest] Zapped encoding")

        if 'if-modified-since' in headers:
            del headers['if-modified-since']

        if 'cache-control' in headers:
            del headers['cache-control']

        if 'Host' in headers:
            try:
                for entry in self.urlMonitor.cookies[self.urlMonitor.Hijack_client]:
                    if headers['Host'] == entry['Host']:
                        log.info("Hijacking session for Host: {}".format(headers['Host']))
                        headers['cookie'] = entry['cookie']
            except KeyError:
                log.error("No captured sessions (yet) from {}".format(self.urlMonitor.Hijack_client))

        return headers

    def getPathFromUri(self):
        if (self.uri.find("http://") == 0):
            index = self.uri.find('/', 7)
            return self.uri[index:]

        return self.uri   

    def handleHostResolvedSuccess(self, address):
        log.debug("[ClientRequest] Resolved Host successfully: {} -> {}".format(self.getHeader('Host'), address))
        Host              = self.getHeader("Host")
        headers           = self.cleanHeaders()
        client            = self.getClientIP()
        path              = self.getPathFromUri()
        url               = 'http://' + Host + path
        self.uri = url # set URI to absolute

        if self.content:
            self.content.seek(0,0)

        postData = self.content.read()

        hostparts = Host.split(':')
        self.dnsCache.cacheResolution(hostparts[0], address)

        if (not self.cookieCleaner.isClean(self.method, client, Host, headers)):
            log.debug("[ClientRequest] Sending expired cookies")
            self.sendExpiredCookies(Host, path, self.cookieCleaner.getExpireHeaders(self.method, client, Host, headers, path))

        Elif self.urlMonitor.isSecureLink(client, url):
            log.debug("[ClientRequest] Sending request via SSL ({})".format((client,url)))
            self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))

        else:
            log.debug("[ClientRequest] Sending request via HTTP")
            #self.proxyViaHTTP(address, self.method, path, postData, headers)
            port = 80
            if len(hostparts) > 1:
                port = int(hostparts[1])

            self.proxyViaHTTP(address, self.method, path, postData, headers, port)

    def handleHostResolvedError(self, error):
        log.debug("[ClientRequest] Host resolution error: {}".format(error))
        try:
            self.finish()
        except:
            pass

    def resolveHost(self, Host):
        address = self.dnsCache.getCachedAddress(Host)

        if address != None:
            log.debug("[ClientRequest] Host cached: {} {}".format(Host, address))
            return defer.succeed(address)
        else:
            return reactor.resolve(Host)

    def process(self):
        log.debug("[ClientRequest] Resolving Host: {}".format(self.getHeader('Host')))
        Host = self.getHeader('Host').split(":")[0]              

        deferred = self.resolveHost(Host)
        deferred.addCallback(self.handleHostResolvedSuccess)
        deferred.addErrback(self.handleHostResolvedError)

    def proxyViaHTTP(self, Host, method, path, postData, headers, port):
        connectionFactory          = ServerConnectionFactory(method, path, postData, headers, self)
        connectionFactory.protocol = ServerConnection
        #self.reactor.connectTCP(Host, 80, connectionFactory)
        self.reactor.connectTCP(Host, port, connectionFactory)

    def proxyViaSSL(self, Host, method, path, postData, headers, port):
        clientContextFactory       = ssl.ClientContextFactory()
        connectionFactory          = ServerConnectionFactory(method, path, postData, headers, self)
        connectionFactory.protocol = SSLServerConnection
        self.reactor.connectSSL(Host, port, connectionFactory, clientContextFactory)

    def sendExpiredCookies(self, Host, path, expireHeaders):
        self.setResponseCode(302, "Moved")
        self.setHeader("Connection", "close")
        self.setHeader("Location", "http://" + Host + path)

        for header in expireHeaders:
            self.setHeader("Set-Cookie", header)

        self.finish()        
1
johnmet

透過プロキシは多かれ少なかれ言語の乱用であり、エンドユーザー側での構成を必要としないため、エンドユーザーに対して透過的です(ワークステーションは通常の要求を行うだけです)。

プロキシが機能するには、フローをインターセプトする必要があり、ワークステーションフローを終了し、クライアントに代わって要求を行います。送信元アドレスは、リモートサーバーのプロキシアドレスになります。 (一部のファイアウォールは、これが当てはまらないクリアテキストトラフィックに対して帯域外分析を実行しますが、通常は「脆弱」であり、クリアテキストのみに制限されます)

SSLリクエストの分析のために、ファイアウォールはフローを終了し、サイトに一致する証明書を提示します。主に、同じ件名と代替名で新しい証明書に署名しますが、それ自体が発行します。
したがって、ワークステーションはsslをファイアウォールと通信し、ファイアウォールはsslをリモートサイトと通信します。通常(透明性)ファイアウォール機関は自己署名/エンタープライズCAであるため、制御不能なワークステーション(ゲスト)はMITMがあることを認識します。
しかし、彼らが「一般的に」信頼できる証明書を使用することを妨げるものは何もありません(そしてそれは正しい証明書を取得するためのお金の問題です)。

pythonコードは「クラシック」プロキシとして機能し、ワークステーションはそれに接続し、プログラムはリモートサイトにリクエストを送信し、応答を元のワークステーションに返します。

TL; Dr:中間者は、名前の状態として、通信の途中にいるため、リモートサーバーから見たIPはプロキシパブリックIPになります(ファイアウォールのパブリックIPである可能性がありますNATルーティングチェーンの後半)

1
Tensibai

this 質問の回答に基づくと、回答は2つの原則の問題です。

  1. プロキシ構成。ヘッダー、特にX-Forwarded-ForX-Client-IPなどのフィールドを編集しないようにプロキシを設定できます。
  2. クライアントの変更。 SSL接続のプロキシにはスプーフィング証明書が必要なため、多くの透過プロキシでは、SSLトラフィックをプロキシなしで通過させることができます。
    したがって、SSLアドレスは「実際の」IPであり、非SSLアドレスはプロキシのアドレスです。
1
Emadeddin