diff --git a/v2rayN/v2rayN/Enums/EGirdOrientation.cs b/v2rayN/v2rayN/Enums/EGirdOrientation.cs
new file mode 100644
index 00000000..e7f9749f
--- /dev/null
+++ b/v2rayN/v2rayN/Enums/EGirdOrientation.cs
@@ -0,0 +1,9 @@
+namespace v2rayN.Enums
+{
+    public enum EGirdOrientation
+    {
+        Horizontal,
+        Vertical,
+        Tab,
+    }
+}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs
index 1bbd9fef..d39001e0 100644
--- a/v2rayN/v2rayN/Global.cs
+++ b/v2rayN/v2rayN/Global.cs
@@ -116,6 +116,7 @@ namespace v2rayN
 
         public static readonly List<string> SpeedPingTestUrls = new() {
             @"https://www.google.com/generate_204",
+            @"https://www.gstatic.com/generate_204",
             @"https://www.apple.com/library/test/success.html",
             @"http://www.msftconnecttest.com/connecttest.txt",
         };
diff --git a/v2rayN/v2rayN/Models/ConfigItems.cs b/v2rayN/v2rayN/Models/ConfigItems.cs
index 6bef1ce5..2ec36a45 100644
--- a/v2rayN/v2rayN/Models/ConfigItems.cs
+++ b/v2rayN/v2rayN/Models/ConfigItems.cs
@@ -119,6 +119,7 @@ namespace v2rayN.Models
         public double mainHeight { get; set; }
         public double mainGirdHeight1 { get; set; }
         public double mainGirdHeight2 { get; set; }
+        public EGirdOrientation mainGirdOrientation { get; set; }
         public bool colorModeDark { get; set; }
         public bool followSystemTheme { get; set; }
         public string? colorPrimaryName { get; set; }
diff --git a/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
index 927edffc..ee5ab7da 100644
--- a/v2rayN/v2rayN/Resx/ResUI.Designer.cs
+++ b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
@@ -2878,6 +2878,15 @@ namespace v2rayN.Resx {
             }
         }
         
+        /// <summary>
+        ///   查找类似 Main layout orientation(Require restart) 的本地化字符串。
+        /// </summary>
+        public static string TbSettingsMainGirdOrientation {
+            get {
+                return ResourceManager.GetString("TbSettingsMainGirdOrientation", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   查找类似 sing-box Mux Protocol 的本地化字符串。
         /// </summary>
diff --git a/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayN/v2rayN/Resx/ResUI.resx
index e96c109b..3808267e 100644
--- a/v2rayN/v2rayN/Resx/ResUI.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.resx
@@ -1249,4 +1249,7 @@
   <data name="menuSetDefaultMultipleServer" xml:space="preserve">
     <value>Multi-server set to active</value>
   </data>
+  <data name="TbSettingsMainGirdOrientation" xml:space="preserve">
+    <value>Main layout orientation(Require restart)</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
index 5cbc26c7..e0f6e20b 100644
--- a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
@@ -1246,4 +1246,7 @@
   <data name="menuSetDefaultMultipleServer" xml:space="preserve">
     <value>多服务器设为活动(多选)</value>
   </data>
+  <data name="TbSettingsMainGirdOrientation" xml:space="preserve">
+    <value>主界面布局方向(需重启)</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
index 77a4851d..0b0321d8 100644
--- a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
@@ -74,6 +74,7 @@ namespace v2rayN.ViewModels
         [Reactive] public string SpeedPingTestUrl { get; set; }
         [Reactive] public bool EnableHWA { get; set; }
         [Reactive] public string SubConvertUrl { get; set; }
+        [Reactive] public int MainGirdOrientation { get; set; }
 
         #endregion UI
 
@@ -171,6 +172,7 @@ namespace v2rayN.ViewModels
             SpeedPingTestUrl = _config.speedTestItem.speedPingTestUrl;
             EnableHWA = _config.guiItem.enableHWA;
             SubConvertUrl = _config.constItem.subConvertUrl;
+            MainGirdOrientation = (int)_config.uiItem.mainGirdOrientation;
 
             #endregion UI
 
@@ -333,6 +335,7 @@ namespace v2rayN.ViewModels
             _config.speedTestItem.speedPingTestUrl = SpeedPingTestUrl;
             _config.guiItem.enableHWA = EnableHWA;
             _config.constItem.subConvertUrl = SubConvertUrl;
+            _config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
 
             //systemProxy
             _config.systemProxyExceptions = systemProxyExceptions;
diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml
index 76827bf1..abaee0ec 100644
--- a/v2rayN/v2rayN/Views/MainWindow.xaml
+++ b/v2rayN/v2rayN/Views/MainWindow.xaml
@@ -466,28 +466,50 @@
                     </DockPanel>
                 </materialDesign:ColorZone>
 
-                <Grid x:Name="gridMain">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="1*" />
-                        <ColumnDefinition Width="10" />
-                        <ColumnDefinition Width="1*" />
-                    </Grid.ColumnDefinitions>
-                    <ContentControl x:Name="tabProfiles" Grid.Column="0" />
-                    <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
-                    <TabControl
-                        x:Name="tabMain"
-                        Grid.Column="2"
-                        HorizontalContentAlignment="Left">
-                        <TabItem x:Name="tabMsgView" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
-                        <TabItem x:Name="tabClashProxies" Header="{x:Static resx:ResUI.TbProxies}" />
-                        <TabItem x:Name="tabClashConnections" Header="{x:Static resx:ResUI.TbConnections}" />
-                    </TabControl>
-
-                    <materialDesign:Snackbar
-                        x:Name="MainSnackbar"
-                        Grid.Column="0"
-                        Grid.ColumnSpan="3"
-                        MessageQueue="{materialDesign:MessageQueue}" />
+                <Grid>
+                    <Grid x:Name="gridMain" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="10" />
+                            <ColumnDefinition Width="1*" />
+                        </Grid.ColumnDefinitions>
+                        <ContentControl x:Name="tabProfiles" Grid.Column="0" />
+                        <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
+                        <TabControl
+                            x:Name="tabMain"
+                            Grid.Column="2"
+                            HorizontalContentAlignment="Left">
+                            <TabItem x:Name="tabMsgView" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
+                            <TabItem x:Name="tabClashProxies" Header="{x:Static resx:ResUI.TbProxies}" />
+                            <TabItem x:Name="tabClashConnections" Header="{x:Static resx:ResUI.TbConnections}" />
+                        </TabControl>
+                    </Grid>
+                    <Grid x:Name="gridMain1" Visibility="Collapsed">
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="1*" />
+                            <RowDefinition Height="10" />
+                            <RowDefinition Height="1*" />
+                        </Grid.RowDefinitions>
+                        <ContentControl x:Name="tabProfiles1" Grid.Row="0" />
+                        <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" />
+                        <TabControl
+                            x:Name="tabMain1"
+                            Grid.Row="2"
+                            HorizontalContentAlignment="Left">
+                            <TabItem x:Name="tabMsgView1" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
+                            <TabItem x:Name="tabClashProxies1" Header="{x:Static resx:ResUI.TbProxies}" />
+                            <TabItem x:Name="tabClashConnections1" Header="{x:Static resx:ResUI.TbConnections}" />
+                        </TabControl>
+                    </Grid>
+                    <Grid x:Name="gridMain2" Visibility="Collapsed">
+                        <TabControl x:Name="tabMain2" HorizontalContentAlignment="Left">
+                            <TabItem x:Name="tabProfiles2" Header="{x:Static resx:ResUI.menuServers}" />
+                            <TabItem x:Name="tabMsgView2" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
+                            <TabItem x:Name="tabClashProxies2" Header="{x:Static resx:ResUI.TbProxies}" />
+                            <TabItem x:Name="tabClashConnections2" Header="{x:Static resx:ResUI.TbConnections}" />
+                        </TabControl>
+                    </Grid>
+                    <materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{materialDesign:MessageQueue}" />
                 </Grid>
             </DockPanel>
             <tb:TaskbarIcon
diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
index edcbc689..3c3a0d8f 100644
--- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
@@ -137,9 +137,28 @@ namespace v2rayN.Views
                 this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
                 this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
                 this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
-                this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.Visibility).DisposeWith(disposables);
-                this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.Visibility).DisposeWith(disposables);
-                this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
+
+                if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
+                {
+                    gridMain.Visibility = Visibility.Visible;
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.Visibility).DisposeWith(disposables);
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.Visibility).DisposeWith(disposables);
+                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
+                }
+                else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
+                {
+                    gridMain1.Visibility = Visibility.Visible;
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.Visibility).DisposeWith(disposables);
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.Visibility).DisposeWith(disposables);
+                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);
+                }
+                else
+                {
+                    gridMain2.Visibility = Visibility.Visible;
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.Visibility).DisposeWith(disposables);
+                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.Visibility).DisposeWith(disposables);
+                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);
+                }
             });
 
             var IsAdministrator = Utils.IsAdministrator();
@@ -152,10 +171,27 @@ namespace v2rayN.Views
 
             MainFormHandler.Instance.RegisterSystemColorSet(_config, this, (bool bl) => { ViewModel?.ModifyTheme(bl); });
 
-            tabProfiles.Content ??= new ProfilesView();
-            tabMsgView.Content ??= new MsgView();
-            tabClashProxies.Content ??= new ClashProxiesView();
-            tabClashConnections.Content ??= new ClashConnectionsView();
+            if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
+            {
+                tabProfiles.Content ??= new ProfilesView();
+                tabMsgView.Content ??= new MsgView();
+                tabClashProxies.Content ??= new ClashProxiesView();
+                tabClashConnections.Content ??= new ClashConnectionsView();
+            }
+            else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
+            {
+                tabProfiles1.Content ??= new ProfilesView();
+                tabMsgView1.Content ??= new MsgView();
+                tabClashProxies1.Content ??= new ClashProxiesView();
+                tabClashConnections1.Content ??= new ClashConnectionsView();
+            }
+            else
+            {
+                tabProfiles2.Content ??= new ProfilesView();
+                tabMsgView2.Content ??= new MsgView();
+                tabClashProxies2.Content ??= new ClashProxiesView();
+                tabClashConnections2.Content ??= new ClashConnectionsView();
+            }
 
             RestoreUI();
             AddHelpMenuItem();
@@ -248,8 +284,16 @@ namespace v2rayN.Views
             if (Height > maxHeight) Height = maxHeight;
             if (_config.uiItem.mainGirdHeight1 > 0 && _config.uiItem.mainGirdHeight2 > 0)
             {
-                gridMain.ColumnDefinitions[0].Width = new GridLength(_config.uiItem.mainGirdHeight1, GridUnitType.Star);
-                gridMain.ColumnDefinitions[2].Width = new GridLength(_config.uiItem.mainGirdHeight2, GridUnitType.Star);
+                if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
+                {
+                    gridMain.ColumnDefinitions[0].Width = new GridLength(_config.uiItem.mainGirdHeight1, GridUnitType.Star);
+                    gridMain.ColumnDefinitions[2].Width = new GridLength(_config.uiItem.mainGirdHeight2, GridUnitType.Star);
+                }
+                else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
+                {
+                    gridMain1.RowDefinitions[0].Height = new GridLength(_config.uiItem.mainGirdHeight1, GridUnitType.Star);
+                    gridMain1.RowDefinitions[2].Height = new GridLength(_config.uiItem.mainGirdHeight2, GridUnitType.Star);
+                }
             }
         }
 
@@ -258,8 +302,16 @@ namespace v2rayN.Views
             _config.uiItem.mainWidth = Utils.ToInt(this.Width);
             _config.uiItem.mainHeight = Utils.ToInt(this.Height);
 
-            _config.uiItem.mainGirdHeight1 = Math.Ceiling(gridMain.ColumnDefinitions[0].ActualWidth + 0.1);
-            _config.uiItem.mainGirdHeight2 = Math.Ceiling(gridMain.ColumnDefinitions[2].ActualWidth + 0.1);
+            if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
+            {
+                _config.uiItem.mainGirdHeight1 = Math.Ceiling(gridMain.ColumnDefinitions[0].ActualWidth + 0.1);
+                _config.uiItem.mainGirdHeight2 = Math.Ceiling(gridMain.ColumnDefinitions[2].ActualWidth + 0.1);
+            }
+            else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
+            {
+                _config.uiItem.mainGirdHeight1 = Math.Ceiling(gridMain1.RowDefinitions[0].ActualHeight + 0.1);
+                _config.uiItem.mainGirdHeight2 = Math.Ceiling(gridMain1.RowDefinitions[2].ActualHeight + 0.1);
+            }
         }
 
         private void AddHelpMenuItem()
diff --git a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml
index 1c10ca0d..05ab9cda 100644
--- a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml
+++ b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml
@@ -528,6 +528,7 @@
                             <RowDefinition Height="Auto" />
                             <RowDefinition Height="Auto" />
                             <RowDefinition Height="Auto" />
+                            <RowDefinition Height="Auto" />
                         </Grid.RowDefinitions>
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition Width="Auto" />
@@ -830,6 +831,21 @@
                             materialDesign:HintAssist.Hint="Convert Url"
                             IsEditable="True"
                             Style="{StaticResource DefComboBox}" />
+
+                        <TextBlock
+                            Grid.Row="21"
+                            Grid.Column="0"
+                            Margin="{StaticResource SettingItemMargin}"
+                            VerticalAlignment="Center"
+                            Style="{StaticResource ToolbarTextBlock}"
+                            Text="{x:Static resx:ResUI.TbSettingsMainGirdOrientation}" />
+                        <ComboBox
+                            x:Name="cmbMainGirdOrientation"
+                            Grid.Row="21"
+                            Grid.Column="1"
+                            Width="300"
+                            Margin="{StaticResource SettingItemMargin}"
+                            Style="{StaticResource DefComboBox}" />
                     </Grid>
                 </ScrollViewer>
             </TabItem>
diff --git a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
index 933c76cc..3ad6f095 100644
--- a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
@@ -4,6 +4,7 @@ using System.IO;
 using System.Reactive.Disposables;
 using System.Windows;
 using System.Windows.Media;
+using v2rayN.Enums;
 using v2rayN.Handler;
 using v2rayN.Models;
 using v2rayN.ViewModels;
@@ -18,8 +19,6 @@ namespace v2rayN.Views
         {
             InitializeComponent();
 
-   
-
             this.Owner = Application.Current.MainWindow;
             _config = LazyConfig.Instance.GetConfig();
             var lstFonts = GetFonts(Utils.GetFontsPath());
@@ -90,6 +89,10 @@ namespace v2rayN.Views
             {
                 cmbSubConvertUrl.Items.Add(it);
             });
+            foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
+            {
+                cmbMainGirdOrientation.Items.Add(it.ToString());
+            }
 
             lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
             cmbcurrentFontFamily.Items.Add(string.Empty);
@@ -145,6 +148,7 @@ namespace v2rayN.Views
                 this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
                 this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
                 this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
+                this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
 
                 this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
                 this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);