diff --git a/app/controllers/admin/ng_words_controller.rb b/app/controllers/admin/ng_words_controller.rb
index e26ca96b8c..17a6306d1a 100644
--- a/app/controllers/admin/ng_words_controller.rb
+++ b/app/controllers/admin/ng_words_controller.rb
@@ -32,7 +32,7 @@ module Admin
     private
 
     def test_words
-      ng_words = settings_params['ng_words'].split(/\r\n|\r|\n/)
+      ng_words = "#{settings_params['ng_words']}\n#{settings_params['ng_words_for_stranger_mention']}".split(/\r\n|\r|\n/).filter(&:present?)
       Admin::NgWord.reject_with_custom_words?('Sample text', ng_words)
     end
 
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index b2bf2afc20..fe37c3234b 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -84,7 +84,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 
     return nil unless valid_status?
     return nil if (reply_to_local? || reply_to_local_account? || reply_to_local_from_tags?) && reject_reply_to_local?
-    return nil if (!reply_to_local_account_following? || !reply_to_local_status_following? || !reply_to_local_from_tags_following?) && reject_reply_exclude_followers?
+    return nil if mention_to_local_but_not_followed? && reject_reply_exclude_followers?
 
     ApplicationRecord.transaction do
       @status = Status.create!(@params)
@@ -139,7 +139,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def valid_status?
-    !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size)
+    valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size)
+
+    valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") if valid && mention_to_local_but_not_followed?
+
+    valid
   end
 
   def accounts_in_audience
@@ -418,11 +422,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def reply_to_local_from_tags?
-    (@mentions.present? && @mentions.any? { |m| m.account.local? })
+    @mentions.present? && @mentions.any? { |m| m.account.local? }
   end
 
   def reply_to_local_from_tags_following?
-    (@mentions.present? && @mentions.none? { |m| m.account.local? && !m.account.following?(@account) })
+    @mentions.nil? || @mentions.none? { |m| m.account.local? && !m.account.following?(@account) }
   end
 
   def reply_to_local?
@@ -433,6 +437,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     !reply_to_local? || replied_to_status.account.following?(@account)
   end
 
+  def mention_to_local_but_not_followed?
+    !reply_to_local_account_following? || !reply_to_local_status_following? || !reply_to_local_from_tags_following?
+  end
+
   def reject_reply_to_local?
     @reject_reply_to_local ||= DomainBlock.reject_reply?(@account.domain)
   end
diff --git a/app/models/admin/ng_word.rb b/app/models/admin/ng_word.rb
index b99c52a714..801c12094e 100644
--- a/app/models/admin/ng_word.rb
+++ b/app/models/admin/ng_word.rb
@@ -18,6 +18,10 @@ class Admin::NgWord
       hashtag_reject?(Extractor.extract_hashtags(text)&.size || 0)
     end
 
+    def stranger_mention_reject?(text)
+      ng_words_for_stranger_mention.any? { |word| include?(text, word) }
+    end
+
     private
 
     def include?(text, word)
@@ -32,6 +36,10 @@ class Admin::NgWord
       Setting.ng_words || []
     end
 
+    def ng_words_for_stranger_mention
+      Setting.ng_words_for_stranger_mention || []
+    end
+
     def post_hash_tags_max
       value = Setting.post_hash_tags_max
       value.is_a?(Integer) && value.positive? ? value : 0
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index 681b13814a..bd7bed3af5 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -38,6 +38,7 @@ class Form::AdminSettings
     status_page_url
     captcha_enabled
     ng_words
+    ng_words_for_stranger_mention
     hide_local_users_for_anonymous
     post_hash_tags_max
     sensitive_words
@@ -91,6 +92,7 @@ class Form::AdminSettings
 
   STRING_ARRAY_KEYS = %i(
     ng_words
+    ng_words_for_stranger_mention
     sensitive_words
     sensitive_words_for_full
   ).freeze
diff --git a/app/views/admin/ng_words/show.html.haml b/app/views/admin/ng_words/show.html.haml
index 9fad862787..3450135c3c 100644
--- a/app/views/admin/ng_words/show.html.haml
+++ b/app/views/admin/ng_words/show.html.haml
@@ -7,6 +7,9 @@
 = simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f|
   = render 'shared/error_messages', object: @admin_settings
 
+  .fields-group
+    = f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint')
+
   .fields-group
     = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint')
 
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 25534bd235..b5e9f34823 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -643,6 +643,8 @@ en:
     ng_words:
       hide_local_users_for_anonymous: Hide timeline local user posts from anonymous
       keywords: Reject keywords
+      keywords_for_stranger_mention: Reject keywords when mention/reply from strangers
+      keywords_for_stranger_mention_hint: Currently this words are checked posts from other servers only.
       keywords_hint: The first character of the line is "?". to use regular expressions
       post_hash_tags_max: Hash tags max for posts
       test_error: Testing is returned any errors
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 8d3a839551..98de29324f 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -643,6 +643,8 @@ ja:
     ng_words:
       hide_local_users_for_anonymous: ログインしていない状態でローカルユーザーの投稿をタイムラインから取得できないようにする
       keywords: 投稿できないキーワード
+      keywords_for_stranger_mention: フォローしていないアカウントへのメンションで利用できないキーワード
+      keywords_for_stranger_mention_hint: フォローしていないアカウントへのメンションにのみ適用されます。現状は外部サーバーから来た投稿のみに適用されます
       keywords_hint: 行を「?」で始めると、正規表現が使えます
       post_hash_tags_max: 投稿に設定可能なハッシュタグの最大数
       test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index 7659ed82a0..3e27c32a1b 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -1334,6 +1334,199 @@ RSpec.describe ActivityPub::Activity::Create do
           expect(status.language).to eq 'en-US'
         end
       end
+
+      context 'when ng word is set' do
+        let(:custom_before) { true }
+        let(:custom_before_sub) { false }
+        let(:content) { 'Lorem ipsum' }
+        let(:ng_words) { 'hello' }
+        let(:ng_words_for_stranger_mention) { 'ohagi' }
+        let(:object_json) do
+          {
+            id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+            type: 'Note',
+            content: content,
+            to: 'https://www.w3.org/ns/activitystreams#Public',
+          }
+        end
+
+        before do
+          Form::AdminSettings.new(ng_words: ng_words, ng_words_for_stranger_mention: ng_words_for_stranger_mention).save
+          subject.perform unless custom_before_sub
+        end
+
+        context 'when not contains ng words' do
+          let(:content) { 'ohagi, world!' }
+
+          it 'creates status' do
+            expect(sender.statuses.first).to_not be_nil
+          end
+        end
+
+        context 'when hit ng words' do
+          let(:content) { 'hello, world!' }
+
+          it 'creates status' do
+            expect(sender.statuses.first).to be_nil
+          end
+        end
+
+        context 'when mention from tags' do
+          let(:recipient) { Fabricate(:user).account }
+
+          let(:object_json) do
+            {
+              id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+              type: 'Note',
+              content: content,
+              tag: [
+                {
+                  type: 'Mention',
+                  href: ActivityPub::TagManager.instance.uri_for(recipient),
+                },
+              ],
+            }
+          end
+
+          context 'with not using ng words for stranger' do
+            let(:content) { 'among us' }
+
+            it 'creates status' do
+              expect(sender.statuses.first).to_not be_nil
+            end
+          end
+
+          context 'with using ng words for stranger' do
+            let(:content) { 'oh, ohagi!' }
+
+            it 'creates status' do
+              expect(sender.statuses.first).to be_nil
+            end
+          end
+
+          context 'with using ng words for stranger but receiver is following him' do
+            let(:content) { 'oh, ohagi!' }
+            let(:custom_before_sub) { true }
+
+            before do
+              recipient.follow!(sender)
+              subject.perform
+            end
+
+            it 'creates status' do
+              expect(sender.statuses.first).to_not be_nil
+            end
+          end
+
+          context 'with using ng words for stranger but multiple receivers are partically following him' do
+            let(:content) { 'oh, ohagi' }
+            let(:custom_before_sub) { true }
+
+            let(:object_json) do
+              {
+                id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+                type: 'Note',
+                content: content,
+                tag: [
+                  {
+                    type: 'Mention',
+                    href: ActivityPub::TagManager.instance.uri_for(recipient),
+                  },
+                  {
+                    type: 'Mention',
+                    href: ActivityPub::TagManager.instance.uri_for(Fabricate(:user).account),
+                  },
+                ],
+              }
+            end
+
+            before do
+              recipient.follow!(sender)
+              subject.perform
+            end
+
+            it 'creates status' do
+              expect(sender.statuses.first).to be_nil
+            end
+          end
+        end
+
+        context 'when a reply' do
+          let(:recipient) { Fabricate(:user).account }
+          let(:original_status) { Fabricate(:status, account: recipient) }
+
+          let(:object_json) do
+            {
+              id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+              type: 'Note',
+              content: 'ohagi peers',
+              inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
+            }
+          end
+
+          context 'with a simple case' do
+            it 'creates status' do
+              expect(sender.statuses.first).to be_nil
+            end
+          end
+
+          context 'with following' do
+            let(:custom_before_sub) { true }
+
+            before do
+              recipient.follow!(sender)
+              subject.perform
+            end
+
+            it 'creates status' do
+              expect(sender.statuses.first).to_not be_nil
+            end
+          end
+        end
+      end
+
+      context 'when hashtags limit is set' do
+        let(:post_hash_tags_max) { 2 }
+        let(:custom_before) { true }
+        let(:object_json) do
+          {
+            id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+            type: 'Note',
+            content: 'Lorem ipsum',
+            tag: [
+              {
+                type: 'Hashtag',
+                href: 'http://example.com/blah',
+                name: '#test',
+              },
+              {
+                type: 'Hashtag',
+                href: 'http://example.com/blah2',
+                name: '#test2',
+              },
+            ],
+          }
+        end
+
+        before do
+          Form::AdminSettings.new(post_hash_tags_max: post_hash_tags_max).save
+          subject.perform
+        end
+
+        context 'when limit is enough' do
+          it 'creates status' do
+            expect(sender.statuses.first).to_not be_nil
+          end
+        end
+
+        context 'when limit is over' do
+          let(:post_hash_tags_max) { 1 }
+
+          it 'creates status' do
+            expect(sender.statuses.first).to be_nil
+          end
+        end
+      end
     end
 
     context 'with an encrypted message' do