STUDY WHILE YOU ARE BORING


  • 首頁

  • 搜索

  • 技术

  • Tags

  • 关于我

Shadowsocks-workerman-php UDP support added

發表於 September 28, 2018   |   作者: Tim   |   分类: 技术   |   评论

原来workerman 实现的 shadowsocks 服务器仅支持 TCP,不支持 UDP,这样导致无法直接兼容 OUTLINE 客户端,网上找了一些资料,主要参考了 swoole-ss 这方面的实现,最终实现了 UDP 支持,顺便兼容 OUTLINE。


以下为修改 server.php 的内容

  1. 增加 UDP 监听
// 初始化worker,监听$PORT端口
$worker = new Worker('tcp://0.0.0.0:'.$PORT);
 $worker2 = new Worker('udp://0.0.0.0:'.$PORT);
 // 进程数量
$worker->count = $PROCESS_COUNT;
$worker2->count=$worker->count = $PROCESS_COUNT;
// 名称
$worker->name = 'shadowsocks-server';
$worker2->name=$worker->name = 'shadowsocks-server';

// UDP support
$worker2->onMessage=function($connection, $buffer)use($METHOD, $PASSWORD)
{
    if (is_null(@$connection->encryptor)){
        $connection->encryptor = new Encryptor($PASSWORD, $METHOD);
    }
    $buffer = $connection->encryptor->decrypt($buffer);
    // 解析socket5头
    $header_data = parse_socket5_header2($buffer);
    // 头部长度
    $header_len = $header_data[3];
    $host = $header_data[1];
    $port = $header_data[2];
    $address = "udp://$host:$port";
    //echo $address."\n";
    
    $remote_connection = new AsyncUdpConnection($address);
    @$remote_connection->source=$connection;
    $remote_connection->onConnect=function ($remote_connection)use ($buffer,$header_len){
        $remote_connection->send(substr($buffer,$header_len));
    };
    $remote_connection->onMessage=function ($remote_connection,$buffer)use($header_data){
        $_header = pack_header($header_data[1],$header_data[0],$header_data[2]);
        $_data = $remote_connection->source->encryptor->encrypt($_header.$buffer);
        $remote_connection->source->send($_data);
    };
    $remote_connection->connect();
    
};

/*
 UDP 部分 返回客户端 头部数据 by @Zac
 //生成UDP header 它这里给返回解析出来的域名貌似给udp dns域名解析用的
*/
function pack_header($addr,$addr_type,$port){
    $header = '';
    //$ip = pack('N',ip2long($addr));
    //判断是否是合法的公共IPv4地址,192.168.1.1这类的私有IP地址将会排除在外
    /*
     if(filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE)) {
     // it's valid
     $addr_type = ADDRTYPE_IPV4;
     //判断是否是合法的IPv6地址
     }elseif(filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)){
     $addr_type = ADDRTYPE_IPV6;
     }
     */
    switch ($addr_type) {
        case ADDRTYPE_IPV4:
            $header = b"\x01".inet_pton($addr);
            break;
        case ADDRTYPE_IPV6:
            $header = b"\x04".inet_pton($addr);
            break;
        case ADDRTYPE_HOST:
            if(strlen($addr)>255){
                $addr = substr($addr,0,255);
            }
            $header =  b"\x03".chr(strlen($addr)).$addr;
            break;
        default:
            return;
    }
    return $header.pack('n',$port);
}

项目代码: https://github.com/firzen/shadowsocks-php

参考:
https://github.com/walkor/shadowsocks-php
https://github.com/shadowsocksBak/shadowsocks-php

php, shadowsocks, workerman, UDP
MISSIONCONTROL 显示器单独空间的区别
生成 OUTLINE客户端兼容 accesskey

钜添

54 文章
2 分類
1 页面
GitHub 日记技术
php apache centos macos mysql https shadowsocks mac 微信 ups svn javascript outline accesskey Chrome Extension letsencrypt ssl free certification certbo wildcard renew cloudflare pgsql 归档 binlog isset array_key_exists redmine axure
© 2021 钜添   |   文章 RSS     |  登录
由 Typecho 强力驱动
主題 - NexT
Send message encrypted and private - Msg2
Build your Under Construction Page without hosting - UnderConstruct.IO