diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py
index 7184d91f7..63b490fd9 100644
--- a/apps/assets/automations/base/manager.py
+++ b/apps/assets/automations/base/manager.py
@@ -1,11 +1,12 @@
 import json
 import os
 import shutil
+import yaml
+
 from collections import defaultdict
 from hashlib import md5
 from socket import gethostname
 
-import yaml
 from django.conf import settings
 from django.utils import timezone
 from django.utils.translation import gettext as _
@@ -239,10 +240,12 @@ class BasePlaybookManager:
             jms_asset, jms_gateway = host['jms_asset'], host.get('gateway')
             if not jms_gateway:
                 continue
+
             server = SSHTunnelForwarder(
                 (jms_gateway['address'], jms_gateway['port']),
                 ssh_username=jms_gateway['username'],
                 ssh_password=jms_gateway['secret'],
+                ssh_pkey=jms_gateway['private_key_path'],
                 remote_bind_address=(jms_asset['address'], jms_asset['port'])
             )
             try:
@@ -252,8 +255,8 @@ class BasePlaybookManager:
                 print('\033[31m %s \033[0m\n' % err_msg)
                 not_valid.append(k)
             else:
-                jms_asset['address'] = '127.0.0.1'
-                jms_asset['port'] = server.local_bind_port
+                host['ansible_host'] = jms_asset['address'] = '127.0.0.1'
+                host['ansible_port'] = jms_asset['port'] = server.local_bind_port
                 servers.append(server)
 
         # 网域不可连接的,就不继续执行此资源的后续任务了
diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py
index 7b6c8818c..afb92a447 100644
--- a/apps/assets/const/host.py
+++ b/apps/assets/const/host.py
@@ -36,7 +36,7 @@ class HostTypes(BaseType):
                 'choices': ['ssh', 'telnet', 'vnc', 'rdp']
             },
             cls.WINDOWS: {
-                'choices': ['rdp', 'ssh', 'vnc']
+                'choices': ['rdp', 'ssh', 'vnc', 'winrm']
             }
         }
 
@@ -58,7 +58,7 @@ class HostTypes(BaseType):
             cls.WINDOWS: {
                 'ansible_config': {
                     'ansible_shell_type': 'cmd',
-                    'ansible_connection': 'ssh',
+                    'ansible_connection': 'smart',
                 },
             },
             cls.OTHER_HOST: {
diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py
index 39d3f3112..eef3269d3 100644
--- a/apps/assets/const/protocol.py
+++ b/apps/assets/const/protocol.py
@@ -10,6 +10,7 @@ class Protocol(ChoicesMixin, models.TextChoices):
     rdp = 'rdp', 'RDP'
     telnet = 'telnet', 'Telnet'
     vnc = 'vnc', 'VNC'
+    winrm = 'winrm', 'WinRM'
 
     mysql = 'mysql', 'MySQL'
     mariadb = 'mariadb', 'MariaDB'
@@ -51,6 +52,13 @@ class Protocol(ChoicesMixin, models.TextChoices):
                 'port': 23,
                 'secret_types': ['password'],
             },
+            cls.winrm: {
+                'port': 5985,
+                'secret_types': ['password'],
+                'setting': {
+                    'use_ssl': False,
+                }
+            },
         }
 
     @classmethod
diff --git a/apps/assets/migrations/0111_auto_20230321_1633.py b/apps/assets/migrations/0111_auto_20230321_1633.py
index 314d2ed7f..fce00cc98 100644
--- a/apps/assets/migrations/0111_auto_20230321_1633.py
+++ b/apps/assets/migrations/0111_auto_20230321_1633.py
@@ -2,6 +2,8 @@
 
 from django.db import migrations, models
 
+from assets.const import AllTypes
+
 
 def migrate_platform_charset(apps, schema_editor):
     platform_model = apps.get_model('assets', 'Platform')
@@ -20,6 +22,11 @@ def migrate_platform_protocol_primary(apps, schema_editor):
         p.save()
 
 
+def migrate_internal_platforms(apps, schema_editor):
+    platform_cls = apps.get_model('assets', 'Platform')
+    AllTypes.create_or_update_internal_platforms(platform_cls)
+
+
 class Migration(migrations.Migration):
 
     dependencies = [
@@ -34,4 +41,5 @@ class Migration(migrations.Migration):
         ),
         migrations.RunPython(migrate_platform_charset),
         migrations.RunPython(migrate_platform_protocol_primary),
+        migrations.RunPython(migrate_internal_platforms),
     ]
diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py
index 20824cba9..300b3dd65 100644
--- a/apps/assets/serializers/platform.py
+++ b/apps/assets/serializers/platform.py
@@ -41,6 +41,9 @@ class ProtocolSettingSerializer(serializers.Serializer):
     # Redis
     auth_username = serializers.BooleanField(default=False, label=_("Auth with username"))
 
+    # WinRM
+    use_ssl = serializers.BooleanField(default=False, label=_("Use SSL"))
+
 
 class PlatformAutomationSerializer(serializers.ModelSerializer):
     class Meta:
diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py
index 6abf6d18e..2695851bb 100644
--- a/apps/ops/ansible/inventory.py
+++ b/apps/ops/ansible/inventory.py
@@ -72,15 +72,14 @@ class JMSInventory:
             var['ansible_ssh_private_key_file'] = account.private_key_path
         return var
 
-    def make_ssh_account_vars(self, host, asset, account, automation, protocols, platform, gateway):
+    def make_account_vars(self, host, asset, account, automation, protocol, platform, gateway):
         if not account:
             host['error'] = _("No account available")
             return host
 
-        ssh_protocol_matched = list(filter(lambda x: x.name == 'ssh', protocols))
-        ssh_protocol = ssh_protocol_matched[0] if ssh_protocol_matched else None
+        port = protocol.port if protocol else 22
         host['ansible_host'] = asset.address
-        host['ansible_port'] = ssh_protocol.port if ssh_protocol else 22
+        host['ansible_port'] = port
 
         su_from = account.su_from
         if platform.su_enabled and su_from:
@@ -97,28 +96,55 @@ class JMSInventory:
             host.update(self.make_account_ansible_vars(account))
 
         if gateway:
-            host.update(self.make_proxy_command(gateway))
+            ansible_connection = host.get('ansible_connection', 'ssh')
+            if ansible_connection in ('local', 'winrm'):
+                host['gateway'] = {
+                    'address': gateway.address, 'port': gateway.port,
+                    'username': gateway.username, 'secret': gateway.password,
+                    'private_key_path': gateway.private_key_path
+                }
+                host['jms_asset']['port'] = port
+            else:
+                host.update(self.make_proxy_command(gateway))
 
     @staticmethod
-    def get_primary_protocol(protocols):
-        if protocols:
-            primary = protocols[0]
-            protocol = primary.name
-            port = primary.port
-        else:
-            protocol = 'null'
-            port = 0
-        return protocol, port
+    def get_primary_protocol(ansible_config, protocols):
+        invalid_protocol = type('protocol', (), {'name': 'null', 'port': 0})
+        ansible_connection = ansible_config.get('ansible_connection')
+        # 数值越小,优先级越高,若用户在 ansible_config 中配置了,则提高用户配置方式的优先级
+        protocol_priority = {'ssh': 10, 'winrm': 9, ansible_connection: 1}
+        protocol_sorted = sorted(protocols, key=lambda x: protocol_priority.get(x.name, 999))
+        protocol = protocol_sorted[0] if protocol_sorted else invalid_protocol
+        return protocol
+
+    @staticmethod
+    def fill_ansible_config(ansible_config, protocol):
+        if protocol.name in ('ssh', 'winrm'):
+            ansible_config['ansible_connection'] = protocol.name
+        if protocol.name == 'winrm':
+            if protocol.setting.get('use_ssl', False):
+                ansible_config['ansible_winrm_scheme'] = 'https'
+                ansible_config['ansible_winrm_transport'] = 'ssl'
+                ansible_config['ansible_winrm_server_cert_validation'] = 'ignore'
+            else:
+                ansible_config['ansible_winrm_scheme'] = 'http'
+                ansible_config['ansible_winrm_transport'] = 'plaintext'
+        return ansible_config
 
     def asset_to_host(self, asset, account, automation, protocols, platform):
-        protocol, port = self.get_primary_protocol(protocols)
+        try:
+            ansible_config = dict(automation.ansible_config)
+        except (AttributeError, TypeError):
+            ansible_config = {}
+
+        protocol = self.get_primary_protocol(ansible_config, protocols)
 
         host = {
             'name': '{}'.format(asset.name.replace(' ', '_')),
             'jms_asset': {
                 'id': str(asset.id), 'name': asset.name, 'address': asset.address,
                 'type': asset.type, 'category': asset.category,
-                'protocol': protocol, 'port': port,
+                'protocol': protocol.name, 'port': protocol.port,
                 'spec_info': asset.spec_info, 'secret_info': asset.secret_info,
                 'protocols': [{'name': p.name, 'port': p.port} for p in protocols],
             },
@@ -131,25 +157,16 @@ class JMSInventory:
         if host['jms_account'] and asset.platform.type == 'oracle':
             host['jms_account']['mode'] = 'sysdba' if account.privileged else None
 
-        try:
-            ansible_config = dict(automation.ansible_config)
-        except Exception as e:
-            ansible_config = {}
-        ansible_connection = ansible_config.get('ansible_connection', 'ssh')
+        ansible_config = self.fill_ansible_config(ansible_config, protocol)
         host.update(ansible_config)
 
         gateway = None
         if not asset.is_gateway and asset.domain:
             gateway = asset.domain.select_gateway()
 
-        if ansible_connection == 'local':
-            if gateway:
-                host['gateway'] = {
-                    'address': gateway.address, 'port': gateway.port,
-                    'username': gateway.username, 'secret': gateway.password
-                }
-        else:
-            self.make_ssh_account_vars(host, asset, account, automation, protocols, platform, gateway)
+        self.make_account_vars(
+            host, asset, account, automation, protocol, platform, gateway
+        )
         return host
 
     def get_asset_sorted_accounts(self, asset):
@@ -194,14 +211,23 @@ class JMSInventory:
         else:
             return None
 
+    @staticmethod
+    def set_platform_protocol_setting_to_asset(asset, platform_protocols):
+        asset_protocols = asset.protocols.all()
+        for p in asset_protocols:
+            setattr(p, 'setting', platform_protocols.get(p.name, {}))
+        return asset_protocols
+
     def generate(self, path_dir):
         hosts = []
         platform_assets = self.group_by_platform(self.assets)
         for platform, assets in platform_assets.items():
             automation = platform.automation
-
+            platform_protocols = {
+                p['name']: p['setting'] for p in platform.protocols.values('name', 'setting')
+            }
             for asset in assets:
-                protocols = asset.protocols.all()
+                protocols = self.set_platform_protocol_setting_to_asset(asset, platform_protocols)
                 account = self.select_account(asset)
                 host = self.asset_to_host(asset, account, automation, protocols, platform)
 
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 310bc9de6..6457f2104 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -65,6 +65,7 @@ pyjwkest==1.4.2
 jsonfield2==4.0.0.post0
 geoip2==4.5.0
 ipip-ipdb==1.6.1
+pywinrm==0.4.3
 # Django environment
 Django==3.2.17
 django-bootstrap3==14.2.0