commmon-netwrok
uto
uto

ShadowSocksとSoftetherを443ポートで同時待ち受け

2020年11月20日

background

最初の記事からかなり日が経ってしまいましたが、ついに本題の記事を書きます。日本語の情報はあまり無かったのでこの記事が他の方の役に立つことを願います。

今回は、ShadowSocksとSoftetherの共存環境を作成しました。

概要を説明すると、443ポートでHAProxyが待ち受けし、通信内容でShadowSocksとSoftetherに通信を振り分けています。SoftetherのクライアントアプリがSNIに対応しているため、HAProxyで判定しています。 また、HAProxyがUDP通信に対応していないため、今回の方法だとSoftetherのUDP高速化機能が使えません。(個人的にはあまり恩恵を受けた記憶がないというか・・・そもそも443ポートを使いたい理由ってセキュリティ的に443くらいしか使えない時だからあまり問題ないかも・・・)

ちなみにShadowSocks libevに拡張機能を追加することで似たようなことができるらしいですが、私の環境ではうまく動きませんでした。ちなみに、後日知人から聞いた話だとSentOS8だとパッケージ名が変わっているものがあるらしく、依存関係で正常動作しないことがあるそうなのでそれが原因だったかもしれません。

今回の記事は以下のことを前提に進めます。もし、一から構築するのであれば他の記事も参考にしてください。

  • CentOS8

  • ShadowSocksがインストールされている

  • Softetherがインストールされている サーバーにドメインが紐ついている

もし、インストールがまだであれば以下の記事を参考にインストールして下さい。

CentOS8にShadowSocks libevを構築する

CentOS8でSoftetherVPNを構築する

ドメインの紐付けは、SNIとかは意識せずに通常の方法でサーバーIPとドメイン名を紐つけてあり、IPが正引き出来ればば大丈夫です。

SetUp HAProxy

今回の主役であるHAProxyをインストール設定していきます。上のリンクでインストールをしている場合既にShadowSocks、Softetherが443ポートを利用しています。このままだと起動時にポートが競合するので一度両ソフトを停止します。 以下のコマンドで停止できます。(上記記事で設定している場合)

#ShadowSocksの停止
systemctl stop ss.service
systemctl disable ss.service
#softetherの停止
systemctl stop vpnserver.service
systemctl disable vpnserver.service
#必要であれば停止の確認をする
systemctl status ss.service
systemctl status vpnserver.service

アプリを停止したら以下のコマンドでHAProxyをインストールします。

dnf -y install haproxy

インストール後、HAProxyのコンフィグファイルを書き換え設定します。

vi /etc/haproxy/haproxy.cfg

追記内容は以下です。

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend https    
 mode	tcp    
 bind   	*:443   
 tcp-request inspect-delay 5s    
 tcp-request content accept if { req.ssl_hello_type 1 }   
 acl vpn-server req_ssl_sni -i <サーバーのドメイン名>#ShadowSocksにドメイン名で接続する場合削除   
 acl vpn-server req_ssl_sni -i <サーバーのドメイン名>/tcp#NAT-T mode    
 use_backend bk-vpn-server if vpn-server        
  default_backend     bk-ss-server

frontend ssl    
 mode tcp    
 bind *:443    
 tcp-request inspect-delay 5s   
 tcp-request content accept  if  HTTP   
 tcp-request content accept if { req.ssl_hello_type 1 }    
 acl vpn-server req_ssl_sni -i <サーバーのドメイン名>#ShadowSocksにドメイン名で接続する場合削除    
 acl vpn-server req_ssl_sni -i <サーバーのドメイン名>/tcp#NAT-T mode   
 use_backend bk-vpn-server if vpn-server     

 default_backend bk-ss-server
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend bk-vpn-server    
 mode 	tcp    
 server      default 127.0.0.1:3000#Softetherのポート
backend bk-ss-server    
 mode        tcp    
 server      default 127.0.0.1:2000#ShadowSocksのポート

振り分けの設定は、Softetherが接続ドメイン名をサーバーに伝えるため、指定のドメイン名を取得した場合はSoftetherに通信を流し、そうでない場合はShadowSocksに通信を流しています。

ちなみにSoftetherは接続の際にhttpsで接続後SSLで通信をするようなので両方の通信を判定できるようにしないと途中で切断されてしまいます。また、前述の通りHAProxyがUDP通信に対応していないため、SoftetherのUDP高速化機能が使えません。そのため、通常の通信からNAT-Tモードと同じ通信になります。

もしShadowSocksにドメイン名で接続したいのであればコンフィグの指定の行を削除することで通信が可能ですが、Softetherの設定が分かりにくくなるのでおすすめはしません。

defaultsやglobalは変更した記憶がないのとバージョンによって違うので記述しません。

Setting Shadowsocks

ShadowSocksのコンフィグファイルから接続用のポート番号を変更します。 以下のコマンドで変更を行って下さい。(私と同じ設定の場合のパスです)

vi /snap/bin/config.json
{
   "server"["[::1]", "127.0.0.1"],
   "mode":"tcp_and_udp",
   "server_port":2000,
   "password":"password",
   "timeout":60,
   "method":"chacha20-ietf-poly1305",
   "nameserver":"1.1.1.1",
   "reuse_port": true,
   "no_delay": true,
   "fast_open": true,
   "ipv6_first": true
}

変更箇所は”server_port”です。 “server_port”は任意のポートを指定して下さい。指定する際はHAProxyのShadowSocksのポート番号と同じになるようにして下さい。

Softetherの設定変更

Softetherは管理マネージャからサーバーに接続し、トップ画面左下にあるポートの削除、追加の項目からTCPポート3000を指定することで設定できます。この際、競合を避けるためTCP443ポートを無効、もしくは削除して下さい。

StartUP

全ての設定が終わったら起動していきます。順番はそこまで気にする必要はありませんが、 ベストはHAProxy→ShadowSocks→Softetherです。

以下のコマンドで起動と、自動起動の登録を行って下さい。

#HAProxyの起動
systemctl start haproxy
systemctl enable haproxy
#ShadowSocksの起動
systemctl stop ss.service
systemctl disable ss.service
#softetherの起動
systemctl stop vpnserver.service
systemctl disable vpnserver.service
#起動の確認をする
systemctl status haproxy
systemctl status ss.service
systemctl status vpnserver.service

ステータスにfaildeなどの表示がなく、各クライアントから同時に接続ができれば正常に設定ができています。

設定に間違えがあると想定外の通信が混じったり競合したりします。(実際競合してネットが途切れ途切れになったことがあります。) そんな時はログを見ることでどの通信がどこに割り振られたかを確認することで原因を究明することができるので参考までに記載しておきます。

以下のコマンドで設定を書き換えます。

vi /etc/rsyslog.conf
# Provides UDP syslog reception
# for parameters see http://www.rsyslog.com/doc/imudp.html
#module(load="imudp") # needs to be done just once #ここと
#input(type="imudp" port="514") #ここのコメントを外す

ログの出力先を設定します。

vi /etc/rsyslog.d/haproxy.conf

以下の内容を入力して下さい。

local2.info                       /var/log/haproxy.log
local2.* ~

最後にHAProxyを再起動して終わりです。

service rsyslog restart 
service haproxy restart

ログは以下に保存されます。

cat /var/log/haproxy.log

brief Summary

今回のSoftetherとShadowSocksの共存サーバーは以前からやりたいと思っていたもので、日本語の情報があまりなかったため、英語の読めない自分は割と苦労しました。この記事が誰かの役に立つことを願います。