1 of 56

プロトコル実装を楽しもう!

PHPで始める

socketプログラミング

市川@cakephper

2025/7/19

PHPカンファレンス関西2025

2 of 56

自己紹介

市川 @cakephper

株式会社ビットフォレスト

CTO / VAddy事業部長

福岡在住

3 of 56

目次

  • PHPのSocket通信
  • PHPで自作HTTP
  • PHPで自作TCP
  • PHPで自作IP
  • PHPで自作イーサネット
  • レイヤーを組み合わせる

4 of 56

PHPのsocket通信

  • socket拡張機能
  • 手軽にTCP/UDPの通信が可能

5 of 56

簡単な

HTTP

プロトコル

HTTP

6 of 56

PHPでSocket通信

7 of 56

TCPを自作

TCP

8 of 56

PHPで

TCPプロトコルを実装

(クライアント側)

9 of 56

モチベーション

  • 仕事に役立つ(可能性)
  • 実装すると理解でき記憶に残る
  • とにかく楽しい

10 of 56

とにかく楽しい😀

  • プロトコルは仕様が決まっている
    • 通信相手が正しく動作する前提
  • 通信できた時の達成感

11 of 56

TCP実装範囲(最低限)

  • 3ウェイハンドシェイク
  • Ack応答
  • クローズ処理(Fin)

12 of 56

TCPはOSが管理

PHPからは

手が出せないのでは?

13 of 56

  • RAWソケット
    • TCP以下の読み書きが可能
    • ROOT権限が必要

14 of 56

TCP実装の流れ

  • socket_create (SOCK_RAW)
  • socket_sendto
  • socket_recvfrom

15 of 56

16 of 56

TCPヘッダ

17 of 56

TCPヘッダのフラグ

18 of 56

TCP 3ウェイハンドシェイク

19 of 56

20 of 56

TCP データ送受信

21 of 56

TCPのデータ送受信が

ほぼ動く状態に

🎉🎉🎉

22 of 56

自作TCP

はまりポイント

23 of 56

TCP 3ウェイハンドシェイクが失敗

SYN RCVD

ステータス

にならない

(netstat)

24 of 56

自作TCPあるある(面白ポイント)

  • 3ウェイハンドシェイクが失敗
    • SYN+ACKをPHPで受け取る(RAWソケット)
    • OSも同時にSYN+ACKを受け取り、知らないTCPのパケットと判断
    • OSがRSTパケットを(勝手に)返す

25 of 56

自作TCPあるある(面白ポイント)

  • 対策方法(雑)
    • iptables -A OUTPUT --dport 80 -p tcp --tcp-flags RST RST -j DROP
    • 外に出ていくRSTパケットを全てDROPする

26 of 56

最低限の実装に1週間程度

  • 3ウェイハンドシェイク
  • Ack応答
  • クローズ処理(Fin)

27 of 56

1週間で楽しめる

自作TCP

28 of 56

IPパケットを

自作

IP

29 of 56

PHPのsocket機能ではIP層は難しい

  • RAWソケットでも無理そう
    • PF_PACKETが指定できない

30 of 56

Linux限定で対応可能

  • socket_create(AF_INET, SOCK_RAW,
  • socket_set_option($socket, IPPROTO_IP, 3 , 1);

IP_HDRINC

31 of 56

32 of 56

33 of 56

自作TCP/IP

  • 自作IPヘッダ + 自作TCPパケット
  • RAWソケットを使って読み書き

34 of 56

1日で楽しめる

自作 IP

35 of 56

自作

イーサネット

Ether

36 of 56

自作イーサネット

  • PHPのsocket機能では無理
  • PF_PACKETが使えない

37 of 56

自作イーサネット

  • C言語/Go言語にする
  • PHPのsocket拡張に手を入れる
  • PHPのFFIを使いlibcのsocketを操作
    • Linux限定だが標準PHPのみで利用可能

FFI: Foreign Function Interface

https://www.php.net/manual/ja/book.ffi.php

38 of 56

FFIでlibcのsocket関数を読み込み

39 of 56

FFI経由でsocketを利用

40 of 56

PHPがあれば

なんでもできる!

💪💪💪

41 of 56

速報

42 of 56

PHP8.5.0 alphaからは

PF_PACKET使えます!

🎉🎉🎉

43 of 56

自作TCP/IP

自作HTTPS

TCP

IP

https

44 of 56

45 of 56

自作TSL on 自作TCP/IP

  • 自作TLS/SSLから呼ぶsocket関係の機能をラップ
  • 自作TCP/IPに差し替え

46 of 56

47 of 56

自作TSL on 自作TCP/IP リポジトリ

  • https://github.com/ichikaway/ore-no-tls-php
    • src/client-ore-tcp-ip.php

48 of 56

さいごに

  • とにかく楽しい
  • 最低限の実装でも動く
  • レイヤーの偉大さを実感

49 of 56

ご清聴ありがとうございました

プロトコル実装を楽しもう!

PHPで始めるsocketプログラミング

市川@cakephper

50 of 56

全部スポンサー中!(宣伝)

  • PHPカンファレンス名古屋 2025 コーヒー
  • PHPerKaigi 2025 シルバー
  • PHPカンファレンス小田原 2025 松
  • PHPカンファレンス新潟2025 シルバー
  • PHPカンファレンス 2025 ゴールド
  • PHPカンファレンス関西2025 ブロンズ
  • PHPカンファレンス福岡 2025 ゴールド

51 of 56

PHPでIPルーター(断念)

  • IPパケットの読み書きはできる
  • 自分宛以外のIPパケットは読めない

52 of 56

53 of 56

TCP

チェックサム

54 of 56

55 of 56

TCPチェックサム

  • 擬似ヘッダ
    • 送信元IP + 宛先IP + TCPヘッダ + データ
    • 別レイヤーのIP情報まで利用している

56 of 56

TCPの歴史

  • 1974年 RFC675
    • SPECIFICATION OF INTERNET TRANSMISSION CONTROL PROGRAM
    • Vinton Cerf, Yogen Dalal, Carl Sunshine
    • Robert Kahn