简体   繁体   中英

PHP Socket connection through proxy

I'm building a webmail-client-like application, and I'm having issues connecting to POP3 through our beloved corp proxy.

Due to client requirements, I'm obligated to use sockets to talk with their POP3 server (they actively specified this is mandatory and they also explained they have a proxy between the app server and the POP) so besides enabling me to work this is kind of the only option I have.

Does anyone know how to do this?

UPDATED TO ADD:

Here's my socket handler:

<?php
class Socket {
  protected $handle = null;
  protected static $status = null;
  public function __construct($server, $port){
    if(!$this->connect($server, $port)){
      throw new UnexpectedValueException("Server $server in port $port unreachable.");
    }
  }
  public static function getStatus(){
    return self::$status;
  }  
  public function write($string){
    fputs($this->handle, $string);
    return $this;
  }
  public function read($lines = 1){
    $lines = abs((int)$lines);//people can be morons
    for($i = 0; $i < $lines; $i++){
      $response []= $this->getLine();
    }
    if($lines==1){
      $response = $response[0];
    }
    return $response;
  }
  public function connect($server, $port){
    $errNo = 0;
    $handle = fsockopen($server, $port);
    if(!$handle){
      return false;
    }
    $this->handle = $handle;
    return $this;
  }
  public function disconnect(){
    if(gettype($this->handle)=='resource'){
      fclose($this->handle);
    }
  }
  public function __destruct(){
    $this->disconnect();
  }
  protected function getLine(){
    return fgets($this->handle);
  }
}

I'm using it like so:

$plug = new Socket('mx.mailserver.com',110);
$plug->write("USER $username\n")->read();
$could = $plug->write("PASS $password\n")->read();
if(strpos($could,'+OK')!==false){
  $mails = $plug->write("STAT\n");
}

And right now our proxy is not letting me out; situation I would like to know how to revert.

First, have you tested with telnet - ie if you are on the same server / workstation that the PHP script is running on, and you issue:

telnet mx.mailserver.com 110

Do you get the greeting? (you're also not reading that - so your read from the command where you send the username is going to get that as a response, so your code will work but largely by accident.

If you can't get it to work via telnet then stop and get that working first - no point proceeding otherwise.

You may need to send \\r\\n at the end of each command.

$plug->write("USER $username\r\n")->read();

So you need to do something like:

$plug = new Socket('mx.mailserver.com',110);
$greeting = $plug->read(); // check this said +OK
$plug->write("USER $username\r\n")->read(); // check this said +OK
$could = $plug->write("PASS $password\r\n")->read();
if(strpos($could,'+OK')!==false) {
    $mails = $plug->write("STAT\r\n");
}

I'm not entirely sure about your strpos() line - but I can't test that right now.

As I say, before you do ANYTHING else verify that it all works ok on Telnet.

If it does, then monitor the server logs (if possible) and see whether you're getting in touch with the POP3 server and what it's getting.

Here's an example sequence:

telnet pop.blah.com 110

+OK Welcome to MailEnable POP3 Server

USER matthew

+OK

PASS mypassword

+OK 

STAT

+OK 0 0

Hope this helps.

Use this for client https://github.com/clue/php-socks

Use this for proxy server https://github.com/clue/psocksd

If your server has more than one public IP and you need these IP act as proxy outgoing, use this for proxy server https://www.inet.no/dante/

Guide to configure proxy to have multi outgoing ip: http://www.inet.no/dante/doc/faq.html#multiple_external_ips

Example config to have multi outgoing ip: http://wiki.jokeru.ro/dante-socks-server

They all work for me

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM