diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index c3bb4f7756..9390af40a9 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1486,6 +1486,8 @@ admin/views/federation.vue:
   chart-spans:
     hour: "1時間ごと"
     day: "1日ごと"
+  blocked-hosts: "ブロック"
+  blocked-hosts-info: "ブロックしたいホストを改行で区切って記述します。"
 
 desktop/views/pages/welcome.vue:
   about: "詳しく..."
diff --git a/src/client/app/admin/views/federation.vue b/src/client/app/admin/views/federation.vue
index 25400393b9..4d0b4b7c77 100644
--- a/src/client/app/admin/views/federation.vue
+++ b/src/client/app/admin/views/federation.vue
@@ -54,7 +54,6 @@
 					<span>{{ $t('latest-request-received-at') }}</span>
 					<template #prefix><fa :icon="faInbox"/></template>
 				</ui-input>
-				<ui-switch v-model="instance.isBlocked" @change="updateInstance()">{{ $t('block') }}</ui-switch>
 				<ui-switch v-model="instance.isMarkedAsClosed" @change="updateInstance()">{{ $t('marked-as-closed') }}</ui-switch>
 				<details>
 					<summary>{{ $t('charts') }}</summary>
@@ -142,6 +141,16 @@
 			<ui-info v-if="instances.length == limit">{{ $t('result-is-truncated', { n: limit }) }}</ui-info>
 		</section>
 	</ui-card>
+
+	<ui-card>
+		<template #title><fa :icon="faBan"/> {{ $t('blocked-hosts') }}</template>
+		<section class="fit-top">
+			<ui-textarea v-model="blockedHosts">
+				<template #desc>{{ $t('blocked-hosts-info') }}</template>
+			</ui-textarea>
+			<ui-button @click="saveBlockedHosts">{{ $t('save') }}</ui-button>
+		</section>
+	</ui-card>
 </div>
 </template>
 
@@ -149,7 +158,7 @@
 import Vue from 'vue';
 import i18n from '../../i18n';
 import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
-import { faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faTrafficLight, faInbox } from '@fortawesome/free-solid-svg-icons';
+import { faBan, faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faTrafficLight, faInbox } from '@fortawesome/free-solid-svg-icons';
 import ApexCharts from 'apexcharts';
 import * as tinycolor from 'tinycolor2';
 
@@ -176,7 +185,8 @@ export default Vue.extend({
 			chartSrc: 'requests',
 			chartSpan: 'hour',
 			chartInstance: null,
-			faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faPaperPlane, faTrafficLight, faInbox
+			blockedHosts: '',
+			faBan, faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faPaperPlane, faTrafficLight, faInbox
 		};
 	},
 
@@ -246,6 +256,10 @@ export default Vue.extend({
 
 	mounted() {
 		this.fetchInstances();
+
+		this.$root.getMeta().then(meta => {
+			this.blockedHosts = meta.blockedHosts.join('\n');
+		});
 	},
 
 	beforeDestroy() {
@@ -477,6 +491,22 @@ export default Vue.extend({
 				}]
 			};
 		},
+
+		saveBlockedHosts() {
+			this.$root.api('admin/update-meta', {
+				blockedHosts: this.blockedHosts.split('\n')
+			}).then(() => {
+				this.$root.dialog({
+					type: 'success',
+					text: this.$t('saved')
+				});
+			}).catch(e => {
+				this.$root.dialog({
+					type: 'error',
+					text: e
+				});
+			});
+		}
 	}
 });
 </script>
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index e34840e907..e4f2e86aaa 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -70,6 +70,13 @@ export const meta = {
 			}
 		},
 
+		blockedHosts: {
+			validator: $.optional.nullable.arr($.str),
+			desc: {
+				'ja-JP': 'ブロックするホスト'
+			}
+		},
+
 		mascotImageUrl: {
 			validator: $.optional.nullable.str,
 			desc: {
@@ -389,6 +396,10 @@ export default define(meta, async (ps) => {
 		set.hiddenTags = ps.hiddenTags;
 	}
 
+	if (Array.isArray(ps.blockedHosts)) {
+		set.blockedHosts = ps.blockedHosts;
+	}
+
 	if (ps.mascotImageUrl !== undefined) {
 		set.mascotImageUrl = ps.mascotImageUrl;
 	}
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index e29edae266..1bd88a1e6d 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -165,6 +165,7 @@ export default define(meta, async (ps, me) => {
 		response.useStarForReactionFallback = instance.useStarForReactionFallback;
 		response.pinnedUsers = instance.pinnedUsers;
 		response.hiddenTags = instance.hiddenTags;
+		response.blockedHosts = instance.blockedHosts;
 		response.recaptchaSecretKey = instance.recaptchaSecretKey;
 		response.proxyAccount = instance.proxyAccount;
 		response.twitterConsumerKey = instance.twitterConsumerKey;