LoginSignup
0
0

More than 5 years have passed since last update.

TyrusのStandalone Modeは0.0.0.0以外をListenすることはできない

Last updated at Posted at 2016-03-28

結論

  • Tyrus1.12のStandalone Modeでは、WebSocketサーバーのListen Addressが0.0.0.0から変更できない。
  • つまり、(ファイヤーウォールがなければ)どこからでもアクセスし放題
  • 制限をかけるには
    • ファイヤーウォールを適切に設定する
    • Jettyを使う

Tyrus in Standalone Modeは0.0.0.0をListenする

スタンドアロンのアプリにWebSocketサーバを組み込みたかったので、調べていたら、Tyrus1.12のドキュメントにTyrus in Standalone Modeという項目を見つけたので試してみました。。

すると、確かに動くのですが、0.0.0.0をlistenしているのが気になりました。スタンドアロンアプリという性質上、localhost以外をlistenしたくなかったのです。

無題.png

制御不可

きっとどこかに設定があるのだと思いドキュメントを探しましたがどうも見当たりません。なので仕方なくソースを追ってみました。

まずはサンプルのソースコードを眺めます。

・・・
public void runServer() {
    Server server = new Server("localhost", 8025, "/websockets", null, EchoEndpoint.class);

    try {
        server.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("Please press a key to stop the server.");
        reader.readLine();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        server.stop();
    }
}
・・・

org.glassfish.tyrus.server.Serverクラスをstartしているようです。見てみましょう。

github Server.java#L20

・・・
/**
 * Start the server.
 */
public void start() throws DeploymentException {
    try {
        if (server == null) {
            server = ServerContainerFactory.createServerContainer(properties);

            for (Class<?> clazz : configuration) {
                server.addEndpoint(clazz);
            }

            server.start(contextPath, port);
            LOGGER.info("WebSocket Registered apps: URLs all start with ws://" + this.hostName + ":" + this.port);
            LOGGER.info("WebSocket server started.");
        }
    } catch (IOException e) {
        throw new DeploymentException(e.getMessage(), e);
    }
}
・・・

org.glassfish.tyrus.spi.Server.ContainerFactoryクラスのcreateServerContainerメソッドを呼んでいるようなので更に潜ります。

github ServerContainerFactory.java#L70

・・・
private static final String CONTAINTER_CLASS =
            "org.glassfish.tyrus.container.grizzly.server.GrizzlyServerContainer";
・・・
public static ServerContainer createServerContainer(final Map<String, Object> properties) {
    ・・・
    if (factory == null) {
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Class factoryClass = (classLoader == null)
                    ? Class.forName(CONTAINTER_CLASS)
                    : classLoader.loadClass(CONTAINTER_CLASS);
            factory = (ServerContainerFactory) factoryClass.newInstance();
        } catch (ClassNotFoundException ce) {
            throw new RuntimeException(ce);
        } catch (InstantiationException ie) {
            throw new RuntimeException(ie);
        } catch (IllegalAccessException ie) {
            throw new RuntimeException(ie);
        }
    }
    return factory.createContainer(properties);
}
・・・

どうやらorg.glassfish.tyrus.container.grizzly.server.GrizzlyServerContainerクラスが実体のようです。見てみます。

github GrizzlyServerContainer.java#L172

・・・
@Override
public void start(final String rootPath, int port) throws IOException, DeploymentException {
    contextPath = rootPath;
    server = new HttpServer();
    final ServerConfiguration config = server.getServerConfiguration();

    final NetworkListener listener = new NetworkListener("grizzly", "0.0.0.0", port);  // ★!!!★
    ・・・
}
・・・

うげ!おもいっきり"0.0.0.0"ってハードコードしてあるし!

ということで、0.0.0.0をlistenしてしまうのは変更不可のようです。

代替案

どうすればよいのでしょうか。

ファイヤーウォールを正しく設定する。

「どうすればよいのでしょうか」といってもどうにもできないので、ちゃんとファイヤーウォールを設定しましょうというのが結論でしょう。不正なリクエストは受け付けないようにすればいい話です。とはいえ、自分用のアプリならいいとして、いろいろな人に配るようなアプリの場合「設定してね」と言う以上のことはできません。設定してくれるかどうかは利用者次第です・・・

別の実装を使う

tyrusの実装がこうなっているというだけなので、tyrusじゃない別の実装を使うというのも良い選択でしょう。ただし、現時点ではドキュメントが少ないですね・・・

ちなみに私はJettyを使いました。

JavaSEでJettyを使ってWebSocket(JSR-356)サーバーを立てた

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0