Apacheは新しいTomcat9ajpに接続できません

Aug 20 2020

Spring bootのバージョンを2.1.4から2.3.2にアップグレードした後、apache2が(ajpによって)Springbootの組み込みTomcatに接続できなくなりました。

次のエラーが表示されます。

[proxy:error] [pid xxxx ] (111)Connection refused: AH00957: AJP: attempt to connect to 10.0.75.1:8500 (10.0.75.1) failed
[proxy_ajp:error] [pid xxxx ] [client xxx ] AH00896: failed to make connection to backend: 10.0.75.1, referer: http://myapp.develop/home/

私は自分の開発環境をこのように設定しています:

  • Angularアプリ(4200で実行されているノードサーバー)

  • スプリングブートバックエンド(ポート8500のTomcatに設定されたajpコネクタ)

  • リクエストを両方のアプリにリダイレクトするように設定された正面のapache2サーバー(Dockerコンテナー上):

    <VirtualHost *:80>
    ServerName myapp.develop
    
    ProxyPass "/home" "http://10.0.75.1:4200/home"
    ProxyPassReverse "/home" "http://10.0.75.1:4200/home"
    
    ProxyPass "/backend" "ajp://10.0.75.1:8500/backend"
    ProxyPassReverse "/backend" "ajp://10.0.75.1:8500/backend"
    

/ etc / hostsのドメイン名でWebアプリにアクセスします:myapp.develop

これは私のSpringBootTomcatの構成です

   Connector connector = new Connector("AJP/1.3");
   connector.setScheme("http");
   connector.setPort(8500);
   connector.setSecure(false);
   connector.setAllowTrace(false);
   ((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);

app.properties内:

tomcat.ajp.port=8500
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true

これはTomcatログです:

o.s.b.w.e.t.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http) 8500 (http)
o.a.c.h.Http11NioProtocol    : Initializing ProtocolHandler ["http-nio-8080"]
o.a.c.a.AjpNioProtocol       : Initializing ProtocolHandler ["ajp-nio-127.0.0.1-8500"]
o.a.c.c.StandardService      : Starting service [Tomcat]
o.a.c.c.StandardEngine       : Starting Servlet engine: [Apache Tomcat/9.0.37]

私はこの変更を疑っています:

  • 8.5.51以降では、AJPコネクタのデフォルトのリッスンアドレスがすべてのアドレスではなくループバックアドレスに変更されました。

それが私にこの問題を引き起こしているのですが、私はそれを解決する方法がわかりません。

回答

5 Prerna Sep 17 2020 at 04:37

Tomcatバージョンをアップグレードするときに同様の問題に直面しました。下記のプロパティをajpコネクタに追加すると、私の場合に役立ちました。

connector.setProperty("address","0.0.0.0");
connector.setProperty("allowedRequestAttributesPattern",".*");
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);

詳細な説明:

あなたの疑いに:

8.5.51以降では、AJPコネクタのデフォルトのリッスンアドレスがすべてのアドレスではなくループバックアドレスに変更されました。

この更新の前は、Tomcat AJPコネクタは任意のIPアドレスからの要求を受け入れることをいとわなかったため、「address」プロパティを明示的に指定する必要はありませんでした。ただし、この更新後のデフォルトの動作では、AJPコネクタはlocalhost(ループバック)としてのみ行われた要求を受け入れます。以下にリストされている「アドレス」プロパティを使用して、リスニング範囲をループバックアドレスだけでなく拡張します。

connector.setProperty("address","0.0.0.0"); // OR connector.setProperty("address","::");

以下のプロパティを使用して、すべてのタイプのリクエスト属性を有効にします(ヘッダー情報がない場合は、特定の属性を有効にします)。認識されないリクエスト属性を持つリクエストは、403レスポンスで拒否されます。

connector.setProperty("allowedRequestAttributesPattern",".*"); 

「secretRequired」プロパティを使用して、ajpを介したリクエストを許可するために、HTTPサーバーとシークレットを交換する必要があるかどうかを定義します。はいの場合は、「シークレット」プロパティも設定します。そうしないと、リクエストは403で失敗します。

((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);

参照:Apache Tomcat8構成リファレンス

AJPプロトコルを使用すると、HTTPコネクタよりもTomcatの内部データ構造を直接操作できるため、セキュリティに関する追加の考慮事項が必要になります。addresssecretsecretRequiredallowedRequestAttributesPattern属性に使用される値には特に注意を払う必要があります。

2 OlafKock Aug 20 2020 at 21:58

このようなコードでコネクタが設定されているのを見たことがありません。むしろserver.xmlで宣言されています。

ただし、コードは

Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(8500);
connector.setSecure(false);
connector.setAllowTrace(false);
((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);

そして後であなたはこの重大な変化について知っていると述べます

8.5.51以降では、AJPコネクタのデフォルトのリッスンアドレスがすべてのアドレスではなくループバックアドレスに変更されました。

両方の組み合わせ:コードでリスニングアドレスを設定することはありません。したがって、デフォルトを使用している可能性があります。また、非ループバックアドレスに転送しようとしているため、この方法でサーバーに到達する方法はありません。

この回答の匿名の編集者が提案connector.setAttribute("address", "0.0.0.0");しましたが、個人的には、server.xmlに保持したいと思います。コネクタは通常、実行時に構成および変更されないため、管理者にテキストファイルを編集させる方がはるかに便利です。 -日-操作。