IPoE/PPPoE併用時(など)に一つの端末から同時に複数の接続経路を利用する

概要

先日公開した当ブログの記事フレッツ光関連の設定について(ドコモ光、ひかり電話、IPoE/IPv4 over IPv6とPPPoEの併用など) - turgenev’s blogや、その他の多くの記事にもある通り、光回線においては適切なプロバイダを選べば、あるいは複数のプロバイダと契約するなどすれば、混雑時でも速度が安定しているIPoE (IPv4 over IPv6)方式と、速度は劣るもののポート開放が自由に行えるPPPoE方式という2通りの方法(接続経路)でインターネットを利用することができるようになります。

この状態は、物理的に配線をつなぎ替えたりWi-FiSSIDを切り替えたりしなくても接続端末側でIPやデフォルトゲートウェイを変更することで両方の経路を利用することができるという意味では両方の経路を「併用」することが可能になっていますが、IPやゲートウェイの変更を行うと接続が一時的に切断され、それを境に一方から他方へと完全に切り替わるため、単一の端末から両方の経路を真に「同時」に利用することはできません。

これを解決しようというのが今回の記事です。この部分に関して解説しているサイトはあまりないのですが、応用すれば結構面白いことができそうで、やる価値はあると思います。例えば、PPPoE経由でサーバーとして公開したいマシンでもブラウザではIPoEでインターネットが使えますし、指定したドメインへの通信のみPPPoE経由にするプロキシサーバーを立ててスマホから利用するといったことも(多分)可能になるはずです。

補足

実際によく利用されるであろう例としてIPoEとPPPoEの併用を挙げていますが、この記事の方法はインターネット側に出ていく複数の経路を同時利用したい全ての場合に応用可能です。例えばPPPoE接続を複数併用する場合でも、ホームルーター光回線を併用する場合でもやることは全く同じです。また接続先が3つ以上あっても同様のやり方で対応できます。

宛先IPによる振り分け

まず基本として、宛先IPによって使用する経路を変更することができます。これはとても容易で、普通のルーターには「静的ルーティング設定」のような項目があるので、そこで宛先IPを指定して、該当するものを別のルーターに丸投げすることができます。例えば、端末側ではIPoE用のルーターデフォルトゲートウェイにしておいて、IPoE用のルーターの静的ルーティング設定でxxx.xxx.xxx.xxxへの通信を全てPPPoE用ルーターに丸投げするようにすれば、端末からxxx.xxx.xxx.xxxへの通信は全てPPPoE経由になります。

また、これはWindowsLinuxのルーティング設定からも可能です。これも多くの解説があるので調べてください。

しかし、これは通常はLAN間の通信に使われる方法で、インターネットへの通信に用いるには欠点があります。というのも、一般にはサイト(ドメイン)が同じでもIPが常に一定であるとは限らず、そうすると目的のドメインだけに確実にPPPoE経由でアクセスすることは難しくなります。

また、一つのIPにIPoEとPPPoEを経由して同時にアクセスすることもこの方法ではできません。

解決策: 一つの端末にIPアドレスを2個割り当てる

そこで、解決策として、一つの接続端末に2個のIPアドレスを割り当てた上で、ポリシーベースルーティングという機能により使うIPアドレスによって使う経路を変えるという方法を取ります。例えば、一つのPCが192.168.1.8と192.168.1.9という2つのIPアドレスを持つようにして、192.168.1.8からインターネット側に行くときはIPoE用のルーター、192.168.1.9側から行くときはPPPoE用のルーターを使うというように設定することができます。

こうすれば、(詳細な設定は後で述べますが)特定のドメインにむけて確実にIPoEあるいはPPPoE経由でアクセスできますし、一つのドメインに同時にIPoEとPPPoEで接続することも可能です。また、ポリシーベースルーティングでは、プロトコルやポート番号を指定した通信の振り分けも可能になります。

ちなみに、「ポリシーベースルーティング」の厳密な定義(どこまでできれば「ポリシーベースルーティング」といえるのか)はいまいちよく理解してないです。

必要なもの/不要なもの

上記の「一つの接続端末に2個のIPアドレスを割り当てる」という機能は、WindowsLinuxにはありますが、(root化したAndroidなどを除く)スマホやゲーム機などにはありません。また、「ポリシーベースルーティング」の機能は、(後述しますが)Windowsには無いようです。従ってこの記事ではLinuxUbuntu)を使用します。実質的にはipコマンドを使うだけなので、LinuxであればRHEL系あるいはそれ以外でも同様にできると思います。Macはわかりません。あとroot権限は必要です。

ただ、先ほど述べたように、Linuxほどの機能を持たない端末であっても、プロキシが使えれば、(そしてもちろん、正しく設定したLinuxが起動していれば、)Linuxを経由することで両方の接続を同時に利用することが可能です。

この記事では接続端末側のLinuxが「ポリシーベースルーティング」を担当しますが、これをルーターにやらせるという方法もあります。しかし、これはどのルーターにも備わっている機能ではなく、数万円するような業務用ルーターYAMAHA製など)が必要になる可能性があります。そのかわりに、「一つの接続端末に2個のIPアドレスを割り当てる」ことはできるが「ポリシーベースルーティング」はできないというような端末(例えばWindows)しかない場合でも本記事の内容が実現できるようになります(多分)。本記事では扱いませんが、対応したルーターがあるならこちらを採用するのも良いでしょう。

また、他の記事ではこの記事と同じ目的で物理的にネットワークカード(NIC)をPCに増設しているものもありますが、この記事のやり方であれば必要ありません。

以上をまとめると、この記事のやり方はroot権限が使えるLinuxUbuntu)を必要としますが、高価なルーターや追加の物理NICは不要です。ルーターNICは数千-数万円しますが、LinuxWindows PCさえあればタダで入れられますからコストは安く済みます。

IPアドレスの追加

ではまず、IPアドレスの追加を行います。

現時点の環境は、192.168.1.1がDHCPサーバー兼用のIPoEルーター、192.168.1.2がDHCP無効のPPPoEルーターで、Linux端末側にはDHCPで192.168.1.8が割り当てられていてデフォルトゲートウェイは192.168.1.1になっている(=IPoEが使われている)とします。

使っているデバイスNIC)の名前はenp3s0とします。「eno1」「wlp2s0」など環境によって違うと思うので適宜書き換えてください。

この状態で下記のコマンドを実行します。

sudo ip addr add 192.168.1.9/24 dev enp3s0 label enp3s0:1

すると、enp3s0に対して192.168.1.9という追加のIPアドレスが割り当てられ、そのIPアドレスをenp3s0:1という名前で参照できるようになります(labelはあってもなくてもあまり変わりませんが)。ip addr showで確認してください(出力結果を記録していなくてすみません)。

ここまでの内容はWindowsでも同等のことができます。また物理NICの追加も必要ありません。

ルーティングテーブルの追加

この状態ではまだ192.168.1.9を指定してインターネットにアクセスしても192.168.1.8と同じルーティングテーブルが使われてしまいます。一つのルーティングテーブルにはデフォルトゲートウェイは一つしか設定できないので、全く別のルーティングテーブルが必要です。

そこで、/etc/iproute2/rt_tablesを編集して、240 pppoeという行を追加します。全体は以下のような感じになると思います。

#
# reserved values
#
255    local
254    main
253    default
0    unspec
#
# local
#
#1    inr.ruhep
240    pppoe

240という数値は1-252の間だったら何でも大丈夫です。ただ200-250くらいを使うのが多いかなとは思います。240とpppoeの間は既存ファイルの内容に倣うとタブスペースなのですが半角スペースでも問題なく動くようです。

これでpppoeという名前の新たなルーティングテーブルが使えるようになりました。

新たなルーティングテーブルの編集

では、こうして作成したpppoeテーブルにデフォルトゲートウェイを追加します。

sudo ip route add default via 192.168.1.2 dev enp3s0 table pppoe

このように、PPPoE用ルーターIPアドレスと使用するデバイス(enp3s0)、テーブル(pppoe)を指定してip route addを実行します。なお、以下のコマンドの「table pppoe」の部分はすべて「table 240」と数値で指定しても変わりません。

必要があれば他の静的ルーティング設定も追加してください。

結果はip route show table pppoeで確認できます。このような1行だけの出力が出るかと思います。

default via 192.168.1.2 dev enp3s0

ルーティングテーブルの選択ルール(ポリシー)を追加

最後に、「192.168.1.9を使用するときにはpppoeというテーブルを使用する」というルールを追加します。これは以下のコマンドでできます。

sudo ip rule add from 192.168.1.9 lookup pppoe

これにより、192.168.1.9を使用するときにはpppoeテーブルが使われます。

さらに細かい条件で指定したければ、備忘録: 【Linux CentOS 7】特定のパケットのみ別のルーティングテーブルを用いて転送する方法(ポリシールーティング)routing - How to create a protocol-based default route using iproute2 - Server Faultみたいな感じで、条件に一致するパケットにmarkを付けておいて、そのmarkに応じて振り分けるという方法もあります。

注意

ここまでで設定は完了です。

ただし、自分の環境では設定変更の直後はPPPoE用ルーターへのpingがしばらく通らず、結果としてPPPoE経由でのインターネット通信もできない状態になることが多くありました。

おそらく、PPPoEルーター(ちなみにBuffaloのWSR-1166DHPL2という安物です)の直下にPCをつないでいるせいで、PCが2つのIPアドレスを持っている状態にうまくルーターが対応できていないのではないかと思われたため、ルーターに接続されている別のスイッチングハブを経由してPCを接続したところ、症状はやや改善しました。しかしこのあたりはやはり同じNICに二つのIPを追加している弊害という感じがするので、どうしても避けたければNICを追加したほうがよさそうです。USBに刺せるものもありますし。

あと、記事では紹介していませんが、出ていくIPではなくポートやプロトコルで振り分けるような場合は、そもそもIPを複数にする必要がないかもしれません。それならばこのような問題は起こりません。ポートによる振り分けは、外部からのアクセスのみPPPoE経由にしたいような場合に有用ですが、内部からのアクセスはエフェメラルポートの中でどれが割り当てられるかわからないため制御が難しくなります。

経路を同時利用してみる

実際に両方の経路を同時利用できるか調べましょう。手軽なのはWAN側IPアドレスを表示してくれる「確認くん」のようなツールを使う方法です。まずは以下のように普通にcurlコマンドでugtop.comのトップページを取得してみます。

curl https://ugtop.com

すると、以前と変わらずIPoE側のIPアドレスが書かれているはずです。では次に、追加した192.168.1.9を明示的に指定してみます。

curl --interface 192.168.1.9 https://ugtop.com

これで先ほどとは異なるPPPoE側のIPが表示されれば成功です。なお、--interface enp3s0:1というふうにlabelの名前で指定することもできます。

ちなみに、MyDNSの更新はcurlでできるので、IPoEを利用しながら、PPPoEのIPアドレスを通知するということが可能になります。

digでIPアドレス取得

ちなみに、IPアドレスを取得する目的であれば、DNSを使うほうが安定しており、応答も高速です。

グローバルIPアドレスをコマンド(curl/dig等)で確認する方法 | 株式会社ビヨンド

digコマンドで自分のグローバルIPアドレスを取得(IPv4・IPv6) | 小林ノート

などに例があります。opendnsを使うのであれば、

dig -4 myip.opendns.com @208.67.222.222 +short

dig -4 -b 192.168.1.9 myip.opendns.com @208.67.222.222 +short

で、IPoE/PPPoEのグローバルIPが取得できます。出力も1行だけなので見やすいです。

このbというのは「bind address」の略で、簡単に言えば外と通信するときに使うアドレスみたいな意味です。他のコマンドでも、IPを明示的に指定するときはたいていinterfaceあるいはbind address的な名前のオプションを使うことになると思います。

両側からポート転送してみる

次は、IPoE側/PPPoE側の両側からのポート転送を試してみましょう。といってもここまでが正しくできていれば何も難しくありません。例えばLinux上で25565ポートにMinecraftが起動しているとしたら、IPoE側からはWAN側ポート20000→LAN側192.168.1.8:25565、PPPoE側からはWAN側ポート30000→LAN側192.168.1.9:25565というように、IPoE用/PPPoE用のアドレスをそれぞれ使って転送設定をすれば、IPoEのアドレスの20000ポートとPPPoEのアドレスの30000ポートの両方からMinecraftに接続できるようになります。192.168.1.9から来た(=PPPoE側から来た)パケットへの応答は192.168.1.9から出ていくので、さっきのルールによってPPPoE側を通ることになり、正しく通信できるというわけです。さっきのルールがないと、返事がIPoE側から出ていってしまうので通信が成立しません。

念の為ですが、bind addressを0.0.0.0に設定(sshトンネルなら-gオプション)して、アプリケーション側で192.168.1.8:25565と192.168.1.9:25565の両方をlistenするように設定することが必要です。Minecraftでは最初からそうなっています。

設定を永続化する

ひとしきり遊んだところで話題を戻しますが、このままだとLinuxを再起動したときにip addr addとip route addの設定が消えてしまうので、設定ファイルに書いて永続化する必要があります。もちろん、/etc/iproute2/rt_tablesの編集内容は消えないのでそこに関しては不要です。

このようなネットワーク関連の設定は、UbuntuDebian系)なら/etc/network/if-up.d/ 以下、/etc/sysconfig/network-scripts/ 以下にスクリプトを作成しておくと、ネットワークが起動するとき(した直後?)に実行してくれます。Ubuntuなら/etc/network/interfaces に直接書く方法もあるようです。基本的にはif [ "$IFACE" = "enp3s0" ]; thenfiで囲んだところに前述のコマンドをそのまま書けばいいのですが、ip ruleに関してはそのままだと実行されるたびに同じルールが何度も追加されてしまうので、明示的にpriorityを指定することを推奨します(例: sudo ip rule add from 192.168.1.9/32 table pppoe priority 5000)。

しかし、手元ではうまくいきませんでした。再起動直後はインターネットに接続できない状態になっており、タスクトレイの有線接続のアイコンからoff→onと一度再起動しないと正常化しませんでした。sleepなどで時間を十分あけるという方法もありそうですが、あまり美しくないので別の方法を調べました。後日試したら普通にできました。ip routeとip addrは書いてたけどip ruleを書くの忘れてたかな…どうやら、networkingを無効化(後述)するとちゃんと動くようです。なんで???

Netplanによる永続化

どうやらUbuntu 17.01以降からはif-upではなくnetplanという新しいシステムを使うように移行してきているということがわかりました。試行錯誤しながらやったらなんか動いたという感じなので細かいことはわかりませんが、こちらも一応できたので、やり方を説明します。

まずnetplanに切り替えるために従来のnetworkingというのを無効化します。そのかわりにsystemd-networkdを有効化します。(networkingを無効化するというのは Ubuntu 18.04 LTS のネットワーク設定がnetplanというものになっているのでその扱い方についてのメモ書き - dshimizu Blog (α版) に書いてあったのですが、あまり他サイトには載っていないので、他にもやり方があるのかもしれません)。

そして、/etc/netplan/(自分のケースでは、古いUbuntuからアップグレードしてきたからか、空フォルダでした)に以下のような99-pppoe.yamlを作成します。

network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0:
      dhcp-identifier: mac
      dhcp4: true
      dhcp6: true
      addresses:
      - 192.168.1.9/24:
          label: "enp3s0-pppoe"
      routes:
      - to: 0.0.0.0/0
        via: 192.168.1.2
        table: 240
      routing-policy:
      - from: 192.168.1.9/32
        table: 240

このように、enp3s0に対してまず従来と同じくdhcpでの割り当てを追加し、その上でaddressesで明示的に192.168.1.9/24を追加してラベルを付けます(インデントの書き方に注意!)。ラベル表記は比較的最近(2020年頃)サポートされたようです。なお、先ほどのip addr addのときのラベルはenp3s0:xxxという形でないと受け入れられませんでしたが、ここでのラベル設定はtestなど任意の文字列が許容されているようです。

DHCPと固定アドレス割り当てを両方やる例は探してもあまりなく、苦労しました。特に、自分の環境ではdhcp-identifier: macがないとIPアドレスが取得されなかったのでここは注意してください(ルーターにもよったりするのかな?)。なお、別に片方をDHCPにする必要はなく、両方固定IPで全く問題ありません。というかそのほうがいいと思います。このときはaddressesに複数書けばよいです。こちらの設定内容は調べれば色々でてきます。あと、DHCPで2つのアドレスを取得するみたいな方法もあるのかもしれませんがさすがに難しそうな気がしたのでやりませんでした。

次に先ほどのip route addに対応する内容として、240番(pppoe)テーブルに、192.168.1.2をデフォルトゲートウェイとする内容を書きます。さらにその下で、ip rule addに対応する内容として、192.168.1.9から出ていく通信がpppoeテーブルを使うように設定します。

なお、ポリシールーティングの書き方に関しては他にも参考サイトがあります(netplanでポリシールーティングする #Ubuntu - Qiita など)。

これで再起動すればうまくいっているはずです。正確には、上記の設定ファイルの内容を反映させるにはsudo netplan applyだけで十分なのですが、networkingの無効化のために完全な再起動が要る、という感じな気がするので、networkingの無効化後に一度でも再起動を経ているなら、sudo netplan applyをしてみてしばらく経ってもダメだったら一応再起動してみる、くらいのノリがいいかと思います。ちなみに手元では、sudo netplan apply のたびにWARNING:root:Cannot call Open vSwitch: ovsdb-server.service is not running.と言われますが、別に問題なさそうです。/etc/systemd/networkとか/etc/systemd/resolveにファイルを置くみたいなことを書いてあるサイトもありますが自分のところでは不要でした。

あと、ip addr showに出てくるlo:とかに対応する設定を上記のyamlには何も書いていませんが、netplan以降後もそこは変わらずそのまま表示されていたのでこれも別に問題はなさそうです。

正常稼働時のip addr show の結果はこんな感じです。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.9/24 brd 192.168.1.255 scope global enp3s0-pppoe
       valid_lft forever preferred_lft forever
    inet 192.168.1.8/24 metric 100 brd 192.168.1.255 scope global secondary dynamic enp3s0
       valid_lft 257337sec preferred_lft 257337sec
    inet6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 14048sec preferred_lft 12248sec
    inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever

IPv6に関してはよくわかっていなくて不安なので一部伏せ字にしてあります。

上記の結果を見るとわかりますが、DHCPで取得されてメインとして使いたい方の192.168.1.8に「secondary」と書かれています。しかし普通にブラウザなどで使う分にはちゃんと192.168.1.8のほうがデフォルトで使われていてとりあえずは問題なさそうです。ここはちょっとよくわかっていません。ip addr addで追加したときはどちらのアドレスにも「secondary」表記は出ていませんでした。

全く同じ問題で悩んでいる人がいて(linux networking - How to add a static secondary IP to a DHCP interface using netplan? - Server Fault)、そこに書いてあるようにDHCPでもらえるアドレスが事前にわかるときはそれを明示的に書いておけばうまくいくようです。設定ファイルを分割して80-dhcp.yaml90-static.yamlみたいにするのは効果がありませんでした。

他にもipコマンドで手動設定したときとは違うところがちょくちょくありましたが、まあ動いているのでいいでしょう。

ただ、この方法にも欠点があり、networkd(さっきのyamlの3行目で指定されているやつ)はGUIフロントエンドがない(探せばあるのかも?)とかWi-Fiに対応していない?(あるいはパスワード含むアクセスポイントの情報をそのまま書かなきゃいけないかもしれない)とか、普段遣いだと従来のNetworkManagerより劣る部分も多々あります。前節最後に書いた通りNetworkManagerを使っても普通に動くことが後に判明してしまったので、特に理由がなければそちらをおすすめします。

HTTPプロキシを立てる

ここまでで設定は完成したので、再び応用編に戻ります。こんどは、PPPoE/IPoEの両方に出ていけるプロキシを立ててみましょう。

まずはhttpプロキシ用に広く使われているsquidを使ってみます。インストール方法など基本的なところは他の記事に譲るとして、/etc/squid/squid.confに以下のように設定します(これも基本的な内容ですが…)。

http_port 3128
http_port 13128
acl ipoe myport 3128
acl pppoe myport 13128
tcp_outgoing_address 192.168.1.8 ipoe
tcp_outgoing_address 192.168.1.9 pppoe

これが設定ファイルの全部というわけではありません。初期状態は「http_port 3128」がどこかに書いてあると思うので、そこに以降の5行を追記する感じでいけると思います。設定内容としては、3128番ポートに来た内容は192.168.1.8から出ていき、13128番ポートに来た内容は192.168.1.9から出ていくという感じになっています。「ipoe」「pppoe」のところは好きに変えて構いません。なお、DHCP前提ですが192.168.1.8を固定した書き方になってしまいました。

あと、ここには書いていませんが、今回のようにインターネット側に行く用途でsquidプロキシを立てるなら、プライベートアドレス(LAN内)へのアクセスはブロックしてもいいかもしれません(万が一外部からアクセスが来てもそれなりに安全)。デフォルトではブロックされていないです。

書いたらsudo systemctl restart squidとして再起動し、curl https://ugtop.com -x http://localhost:13128などのコマンドで動作を確認しましょう。

ポートで分けるのではなく、192.168.1.8:3128ならipoe、192.168.1.9:3128ならpppoe(あるいは逆でも)といった設定もできます。(myportのかわりにmyipを使うことになります)

他の記事としては複数の IP アドレスを使用した Squid プロキシの構成TOAST Instance 1台に複数のグローバルIPを割り当てる | NHN Cloud Meetupも参考にしてみてください。

このHTTPプロキシをProxy SwitchyOmegaやFoxyproxyのようなブラウザ拡張と併用すれば、特定ドメインだけはPPPoE経由でアクセスするようなことが可能になります。あるいはプロキシ内で接続先ドメインによって振り分けることもできる(プロキシはDNSよりも先に使われるので)と思いますが、そこまでは自分のところでは試していないので他サイトをご参照ください。

自分の環境では初期状態だとhttp_access allow localnetの行がコメントアウトされていて他のマシンから接続できませんでしたが、この行を有効にすれば、LAN内の他のマシンからでもプロキシが使えるようになります(localnetの中身はもともとのsquid.confの中に書かれているはずです)。

SOCKSプロキシを立てる

HTTPプロキシに比べるとややマニアックですが、SOCKSというプロキシの仕組みもあります。ssh -Dで立てられることで知られているやつです。パフォーマンスがいいとかSOCKS5だとUDPも通るとか、利点もあるようです。

LinuxだとdanteというSOCKSプロキシのソフトがあります。これも同様に、/etc/danted.confに以下のように設定します。(他にもいろいろな設定はありますが最低限これだけでも動くはずです)

internal: enp3s0 port=3129
external: enp3s0
internal: enp3s0-pppoe port=3129
external: enp3s0-pppoe
external.rotation: same-same

socksmethod: none
clientmethod: none
client pass {
  from: 0.0.0.0/0  to: 0.0.0.0/0
}
socks pass {
  from: 0.0.0.0/0 to: 0.0.0.0/0
}

external.rotation: same-sameを指定することで、アクセスが来たIPと同じIPから出ていくように設定しています(DHCP前提だったのもあってここではラベル名で指定していますが、IPも書けます)。ポートごとに振り分けるやり方があるかはわかりませんでした(多分ない)。このままだと、LAN内からならちゃんと使えますが、IPoEのインターネット側から入ってPPPoE方面のプロキシを使うようなことができません。そうしたいときは、3129番だけでなく13129番とかでもリッスンするようにして、192.168.1.8:13129がPPPoE側、192.168.1.9:3129がIPoE側から出て行くようにポート限定でip ruleを設定すればsquidと同等の使い勝手になります。

from: 0.0.0.0/0  to: 0.0.0.0/0がちょっとガバガバな気もしますが、ルーターで無駄にポートを開放しすぎたりしていなければ外からは入ってこないはずなので問題ないでしょう。

これもsudo systemctl restart dantedで再起動したら、curl https://ugtop.com -x socks5h://192.168.1.9:3129のようにして試してみましょう。http://ではなくsocks5h://としているのに注意してください。LAN内の他のマシンからもちゃんとアクセスできることを確認しましょう。

SOCKSプロキシはdante以外だと3proxyというのもあって、こちらだとsquidのようにポートごとにoutgoing IPを設定することができました。以下のような3proxy.cfgファイルを指定して3proxy 3proxy.cfgとします。ちゃんと動くソフトですが細部のつくりはかなり雑で、3proxy.cfgが存在しなくてもまともにエラーが出なかったりするので注意してください。この「socks」というのは実行ファイル名を指定しているようです。debパッケージでもソースからのビルド(socksにパスは通っていないが3proxyと同じディレクトリにある)でもちゃんと動くのを確認しました。

log 3proxy.log D
socks -p3129 -e192.168.1.8
socks -p13129 -e192.168.1.9

sshの-Dではoutgoing IPを指定することはできません(linux - Bind outgoing SOCKS-server traffic to a specific IP - Server Fault)。uidなどで振り分けることはできるようです(proxy - How can I configure the source ip to use for ssh dynamic forwards - Super User)。

補足: PCから直接PPPoE接続

PPPoEとIPoEを併用する場合、上位のIPoEルーターでPPPoEパススルーをするなどして、PCで直接PPPoE接続をするという方法もあります。PCが直接インターネットに晒されるため、必ず事前にsudo ufw enableなどとファイアウォールを有効にしておく必要があります。これも一応試してみました。

まずpppoe接続は【2022年版】Ubuntu 20.04.4 LTS で PPPoE接続する方法 #Ubuntu - Qiitaのようにpppoeconfを使うとできます(pppoeとかpppconfigとかいうのも見ましたが、どう違うのかあまりわかってないです)。ip addr showで確認すると、ppp0:という新たな仮想的なNICのようなものが追加されてPPPoEの設定ができていることがわかります。

ただし、途中のメッセージにある通り、「defaultroute」というオプションが自動で設定されてしまい、インターネット通信のデフォルトとしてPPPoEを選択するルールが追加されてしまっています(ip route showで確認できる)。そこで、ip route delでそれを消した上で/etc/ppp/peers/dsl-providerに行ってdefaultrouteの行を削除します。これで次回からはPPPoEがデフォルトとして選ばれなくなります。この状態でも、curlの--interfaceなどでppp0を指定することでPPPoE接続が使えるため、2つの接続を併用することができます。

ただし、ppp0に割り当てられるアドレスは変動するので、squidやdantedでIPを指定して恒久的な設定を追加することはできません。実はdantedのほうではIPのかわりにインターフェイスのラベル(enp3s0など)を指定することもできるのですが、そこでppp0を指定してもダメでした。どうやら、全体のデフォルトゲートウェイ(mainテーブルのデフォルトゲートウェイ)がppp0に向いていないとdanteがppp0からインターネットに出ていけないようです(curlはできるのに)。

Linux自体をPPPoEルータ化するようなことも頑張ればできるみたいなので、原理的には何か方法はあるのではないかと思うのですが、Linuxで直接接続したPPPoE接続を選択的に使えるようなプロキシを立てるのは少し難しそうです。別にこれが是非とも必要というわけではなかったので今回はここで諦めました。この記事の方法でやるのであれば、PPPoE接続の数だけルーターが必要そうです。試してはいませんがiptablesのMASQUERADEとかをすれば普通にできるのではないかと思います。

補足の補足: Wi-Fi環境でpppoeconfで設定したら直後はつながるのですが再起動後にWi-Fiに一切つながらなくなりました。Ubuntuでpppoeconfを設定、再起動するとネットワークに繋がらなくなってしまいますと完全に同じ状態です。そこに書いてある通りに/etc/network/interfacesを最初の1行(source /etc/network/interfaces.d/*)以外コメントアウトして再起動したら復活しました。別PCの設定ファイルではこの行が無いこともあり、実際に完全に空のファイルでも動作するようです。

関連記事

需要はあるようで、他にも似たようなことをやっている記事があります。物理NICを追加したりヤマハルーターを使ったりといったコストのかかるものもありますが、参考にどうぞ。

ルータ2台体制によって自宅サーバにIPv4でもIPv6でもアクセスできるようにした – コンちゃんの「無いなら作ればいいじゃない!」 netplanを使ってLinuxにIPを2つ設定していて、この記事にかなり近い内容です。ただし、IPv4をPPPoE、IPv6をIPoEという形で分けているので、サーバーPCでのIPv4通信ではIPoEを使うことができません。

サーバー兼用パソコンでIPoEとPPPoEを併用してみた : salvia NICを増設しています。WindowsとBuffaloルーターの構成なので、PC側のアドレスでのゲートウェイ切り替えはできず、ルーター側の静的ルーティングで振り分けています。接続先ドメインのIPが変わると問題になりそうです。

DS-Lite/PPPoE併用環境で自宅サーバの通信だけPPPoEを通す | 6715.jp YAMAHAルーターを使っています。HTTPサーバーがPPPoEで公開できればいいだけなので、ポート番号で振り分けており、IPの追加はしていません。

CentOSでOCNバーチャルコネクト | QuintRokkこちらも同じくポート番号での振り分けについて最後の方で解説されています。PPPoEはPCから直接つないでいるようです。

IPv6 DS-Lite環境下で特定のポートのサーバを公開する 気まま研究所 NICを増設したりIPv6を無効にしたり仮想マシンを使ったりと色々違っていて完全に理解はできていないのですが、似たようなことをやっているようです。

また、Windowsではこのようなポリシーベースルーティングができないという情報は以下の記事にありました。

networking - Choosing gateway based on Source IP in Windows - Server Fault

Can I have multi Routing Tables in Windows? : networking

まとめ

というわけで、高価なルーターや追加NICがなくても、PPPoEとIPoEのような2種類のインターネット接続を良い感じに同時に使えることがわかりました。

何か誤り・疑問などあればお気軽にコメントをお願いします。